考虑区间dp
dp[i][j][k]表示区间[i,j]可不可以缩成字符k
dp[i][j][k]=-1表示没算过 0表示不可以 1表示可以
dp[i][j][k]=1当且仅当
dp[l][j][a]=1 且 dp[j+1][r][b]=1且ab可以转化成k
#include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();} return x*f; } const char name[]={'W','I','N','G'}; int hash[255]; int dp[205][205][4]; char a[30][30][2]; int W[5]; char str[1000]; bool dfs(int l,int r,int k) { if(l==r)return str[l]==name[k]; int &res=dp[l][r][k]; if(~res)return res; for(int i=1;i<=W[k];i++) { for(int j=l;j<=r-1;j++) { if(dfs(l,j,hash[a[k][i][0]]) && dfs(j+1,r,hash[a[k][i][1]])) return res=1; } } return res=0; } int main() { memset(dp,-1,sizeof(dp)); hash['W']=0,hash['I']=1,hash['N']=2,hash['G']=3; for(int i=0;i<4;i++)W[i]=read(); for(int i=0;i<4;i++) for(int j=1;j<=W[i];j++) scanf("%s",a[i][j]); scanf("%s",str+1); int len=strlen(str+1); int flag=0; for(int i=0;i<4;i++) { if(dfs(1,len,i)) { flag=1; printf("%c",name[i]); } } if(!flag)printf("The name is wrong!"); return 0; }