bzoj2121 字符串游戏(区间dp)
Posted aaddvvaanntteezz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2121 字符串游戏(区间dp)相关的知识,希望对你有一定的参考价值。
题意
有一个主串$L$,和一个模式串集$S$,每次可以从主串中删除一个模式串,删除后主串剩余的两部分合并,求能得到的主串的最小长度题解
 - 挺神仙的dp
查看代码
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i = (a);i <= (b);++i)
typedef long long ll;
const int maxn = 1e5+5;
const int mod = 1e9+7;
ll qpow(ll a,ll b){ll res = 1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}}
struct graph
{
int head[maxn],nxt[maxn<<1],to[maxn<<1],w[maxn<<1],sz;
void init(){memset(head,-1,sizeof(head));}
graph(){init();}
void push(int a,int b,int c){nxt[sz]=head[a],to[sz]=b,w[sz]=c,head[a]=sz++;}
int& operator[](const int a){return to[a];}
};
char s[153];
char t[32][22];
bool f[153][153][32][22];
bool ok[153][153];
int dp[153];
int len[32];
int main()
{
#ifndef ONLINE_JUDGE
freopen("simple.in","r",stdin);
freopen("simple.out","w",stdout);
#endif
int n,m;
scanf("%s%d",s+1,&m);
for(int i = 1;i <= m;++i)scanf("%s",t[i]+1),len[i]=strlen(t[i]+1);
n = strlen(s+1);
for(int i = 1;i <= n;++i){
for(int j = 1;j <= m;++j){
if(s[i]==t[j][1]){
f[i][i][j][1]=1;
if(len[j]==1)ok[i][i]=1;
}
}
}
for(int width = 2;width <= n;++width){
for(int i = 1,j;i <= n;++i){
j = i+width-1;
if(j>n)break;
for(int k = 1;k <= m;++k){
for(int l = 1;l <= len[k];++l){
if(s[j]==t[k][l]){
f[i][j][k][l]|=f[i][j-1][k][l-1];
}
for(int p = i;p < j;++p){
if(ok[p+1][j])f[i][j][k][l]|=f[i][p][k][l];
}
}
ok[i][j]|=f[i][j][k][len[k]];
}
}
}
for(int i = 1;i <= n;++i){
if(ok[1][i])dp[i]=0;
else dp[i]=dp[i-1]+1;
for(int j = 1;j < i;++j){
if(ok[j+1][i])dp[i]=min(dp[i],dp[j]);
}
}
cout<<dp[n]<<endl;
return 0;
}
以上是关于bzoj2121 字符串游戏(区间dp)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj5147&&bzoj2121&&loj6701 字符串游戏
[BZOJ 1032][JSOI2007]祖码Zuma(区间Dp)