传送门biu~
区间dp,f[i][j][k]表示区间[i,j]能否由字母k来代替,所以只需要在k能被ab代替时用f[i][p][a]和f[p+1][j][b]来更新f[i][j][k]就可以了。记忆化。
#include<bits/stdc++.h>
using namespace std;
int m;
int t[4],ans[505],q[505];
char c[505],a[4][20][2];
int f[505][505][4];
bool dp(int l,int r,int k){
if(l==r){
if(c[l]==ans[k]) return 1;
return 0;
}
int &res=f[l][r][k];
if(~res) return res;
else{
for(int i=1;i<=t[k];++i){
for(int j=1;j<=r-1;++j){
if(dp(l,j,q[a[k][i][0]]) && dp(j+1,r,q[a[k][i][1]])){
res=1;
return 1;
}
}
}
res=0;
return 0;
}
}
int main(){
memset(f,-1,sizeof(f));
q['W']=0;q['I']=1;q['N']=2;q['G']=3;
ans[0]='W';ans[1]='I';ans[2]='N';ans[3]='G';
for(int i=0;i<=3;++i) scanf("%d",&t[i]);
for(int i=0;i<=3;++i)
for(int j=1;j<=t[i];++j)
scanf("%s",a[i][j]);
scanf("%s",c+1);
int len=strlen(c+1);
bool flag=0;
for(int i=0;i<=3;++i){
if(dp(1,len,i)){
flag=1;
printf("%c",ans[i]);
}
}
if(!flag) printf("The name is wrong!");
return 0;
}