题意
题解
傻逼区间
DP
反着考虑,就变成每次合并两个相邻字符变成一个新字符。
f[i][j][0..3]
表示
[i,j]
到是否可以合并成某字符。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=305;
struct data{
int m,a[20][2];
} lst[5];
int n;
bool f[maxn][maxn][4];
char a[maxn];
int hhh[300];
int main(){
memset(hhh,255,sizeof(hhh)); hhh['W']=0; hhh['I']=1; hhh['N']=2; hhh['G']=3;
freopen("bzoj1055.in","r",stdin);
freopen("bzoj1055.out","w",stdout);
scanf("%d%d%d%d",&lst[0].m,&lst[1].m,&lst[2].m,&lst[3].m);
for(int k=0;k<=3;k++){
char s[4];
for(int i=1;i<=lst[k].m;i++) scanf("%s",s), lst[k].a[i][0]=hhh[s[0]], lst[k].a[i][1]=hhh[s[1]];
}
scanf("%s",a+1); n=strlen(a+1);
for(int i=1;i<=n;i++) if(0<=hhh[a[i]]&&hhh[a[i]]<=3) f[i][i][hhh[a[i]]]=true;
for(int L=2;L<=n;L++)
for(int i=1,j=L;j<=n;i++,j++)
for(int k=0;k<=3;k++){ //f[i][j][k]
for(int t=i;t<=j-1;t++)
for(int tt=1;tt<=lst[k].m;tt++) f[i][j][k]|=(f[i][t][lst[k].a[tt][0]]&&f[t+1][j][lst[k].a[tt][1]]);
}
bool pd=false;
if(f[1][n][0]) putchar('W'), pd=true;
if(f[1][n][1]) putchar('I'), pd=true;
if(f[1][n][2]) putchar('N'), pd=true;
if(f[1][n][3]) putchar('G'), pd=true;
if(!pd) printf("The name is wrong!");
return 0;
}