题解:
一道简单的dp题。定义f[i][j][c]表示i~j这一区间中的所有字母能否缩成c这一字母。转移就是:f[i][j][c]=f[i][k][c1]&& f[k+1][c2]&&(c1c2>>c,i<=k<=j)。字符串处理一下即可。
代码如下:
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int maxn=205;
int n,a[5][maxn],hsh[5][maxn];
bool f[maxn][maxn][6];
char s[maxn],p[maxn];
int get(char ch){
if (ch=='W') return 1;
else if (ch=='I') return 2;
else if (ch=='N') return 3;
else if (ch=='G') return 4;
}
int read(){
int x=0; char ch=getchar();
while (ch!='W'&&ch!='I'&&ch!='N'&&ch!='G') ch=getchar();
return get(ch);
}
int main(){
p[1]='W',p[2]='I',p[3]='N',p[4]='G';
scanf("%d %d %d %d",&a[1][0],&a[2][0],&a[3][0],&a[4][0]);
for (int i=1;i<=4;i++)
for (int j=1;j<=a[i][0];j++) a[i][j]=read()*10+read(),hsh[i][a[i][j]]=i;
scanf("%s",s+1);
n=strlen(s+1);
for (int i=1;i<=n;i++) f[i][i][get(s[i])]=1;
for (int l=2;l<=n;l++)
for (int i=1;i<=n-l+1;i++) {
int j=i+l-1;
for (int k=i;k<j;k++)
for (int k1=1;k1<=4;k1++)
for (int k2=1;k2<=4;k2++)
for (int k3=1;k3<=4;k3++)
if (f[i][k][k1]==1&&f[k+1][j][k2]==1&&hsh[k3][k1*10+k2]>0) f[i][j][k3]=1;
}
bool check=0;
for (int i=1;i<=4;i++) if (f[1][n][i]==1) {printf("%c",p[i]); check=1;}
if (check==0) printf("The name is wrong!\n");
return 0;
}