http://codeforces.com/problemset/problem/1149/B
dp[i]][j][k]表示第一个串前i位第二个串前j位....能由word of universe 的最短的多少位形成。
然后 - 操作,就全部情况赋值为n+1,+操作,就全部更新一遍[i][j][len[3]+1]需要去全部得到,那么就i=0-》len[1],j=0->len[2]这样去枚举,然而dp[i][j][len[3]+1]=nxt[ min(dp[i-1][j][len[3]+1],dp[i][j-1][len[3]+1],dp[i][j][len[3]]) ],因为我们是从头到尾得更新新增的len[3]+1,所以这样转移才能覆盖全部情况,得出最小值。
感觉越说越乱,其实自己也没有理解得很清楚,知道状态后都不知道怎么转移。。。
#include<bits/stdc++.h>
#define maxl 100010
using namespace std;
int n,q;
int len[4],last[maxl];
int a[4][252],nxt[maxl][26];
int dp[252][252][252];
char s[maxl],opt[3],ch[3];
inline void prework()
{
scanf("%d%d",&n,&q);
scanf("%s",s+1);
for(int i=0;i<26;i++)
last[i]=n+1,nxt[n][i]=n+1;
for(int i=n;i>=1;i--)
{
for(int j=0;j<26;j++)
nxt[i][j]=last[j];
last[s[i]-'a']=i;
}
for(int j=0;j<26;j++)
nxt[0][j]=last[j],nxt[n+1][j]=n+1;
}
inline void ud(int &a,int b)
{
a=min(a,b);
}
inline void mainwork()
{
memset(dp,0x3f,sizeof(dp));
dp[0][0][0]=0;int id;
while(q--)
{
scanf("%s%d",opt,&id);
if(opt[0]=='+')
{
scanf("%s",ch);
a[id][++len[id]]=ch[0];
if(id==1)
{
for(int i=0;i<=len[2];i++)
for(int j=0;j<=len[3];j++)
{
ud(dp[len[1]][i][j],nxt[ dp[len[1]-1][i][j] ] [ a[1][len[1]]-'a']);
if(i>0)
ud(dp[len[1]][i][j],nxt[ dp[len[1]][i-1][j] ] [ a[2][i]-'a']);
if(j>0)
ud(dp[len[1]][i][j],nxt[ dp[len[1]][i][j-1] ] [ a[3][j]-'a']);
}
}
else if(id==2)
{
for(int i=0;i<=len[1];i++)
for(int j=0;j<=len[3];j++)
{
if(i>0)
ud(dp[i][len[2]][j],nxt[ dp[i-1][len[2]][j] ] [ a[1][i]-'a']);
ud(dp[i][len[2]][j],nxt[ dp[i][len[2]-1][j] ] [ a[2][len[2]]-'a']);
if(j>0)
ud(dp[i][len[2]][j],nxt[ dp[i][len[2]][j-1] ] [ a[3][j]-'a']);
}
}
else if(id==3)
{
for(int i=0;i<=len[1];i++)
for(int j=0;j<=len[2];j++)
{
if(i>0)
ud(dp[i][j][len[3]],nxt[ dp[i-1][j][len[3]] ] [ a[1][i]-'a']);
if(j>0)
ud(dp[i][j][len[3]],nxt[ dp[i][j-1][len[3]] ] [ a[2][j]-'a']);
ud(dp[i][j][len[3]],nxt[ dp[i][j][len[3]-1] ] [ a[3][len[3]]-'a']);
}
}
}
else
{
if(id==1)
{
for(int i=0;i<=len[2];i++)
for(int j=0;j<=len[3];j++)
dp[len[1]][i][j]=n+1;
}
else if(id==2)
{
for(int i=0;i<=len[1];i++)
for(int j=0;j<=len[3];j++)
dp[i][len[2]][j]=n+1;
}
else if(id==3)
{
for(int i=0;i<=len[1];i++)
for(int j=0;j<=len[2];j++)
dp[i][j][len[3]]=n+1;
}
len[id]--;
}
if(dp[len[1]][len[2]][len[3]]<=n)
puts("YES");
else
puts("NO");
}
}
int main()
{
prework();
mainwork();
return 0;
}