首先通过hash建树
设f[i][j]表示第i个特殊符号从P的第j位开始匹配能到达哪里
记忆化搜索,对于底层贪心匹配。
#include<cstdio> #include<cstring> using std::strlen; const int N=510,M=2010; char a[10],tmp[10],b[N][10],s[M]; int T,n,m,i,j,k,h[N],son[N][2],len[N],f[N][M]; inline int hash(char a[]){ int t=0,j=strlen(a); for(int i=0;i<5;i++)t=t*27+(i<j?(a[i]-‘A‘+1):0); return t; } int F(int x,int y){ if(~f[x][y])return f[x][y]; if(son[x][0])return f[x][y]=F(son[x][1],F(son[x][0],y)); int j=y; for(int i=0;j<m&&i<len[x];i++)if(b[x][i]==s[j])j++; return f[x][y]=j; } int main(){ for(scanf("%d",&T);T--;puts(F(j,0)<m?"NO":"YES")){ scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%s%s%s",a,tmp,b[i]),h[i]=hash(a); if(b[i][0]>=‘a‘&&b[i][0]<=‘z‘)son[i][0]=0,len[i]=strlen(b[i]); else son[i][0]=hash(b[i]),scanf("%s",tmp),scanf("%s",tmp),son[i][1]=hash(tmp); } for(i=1;i<=n;i++)if(son[i][0])for(j=0;j<2;j++)for(k=1;k<=n;k++)if(son[i][j]==h[k]){son[i][j]=k;break;} scanf("%s%s",a,s),m=strlen(s); for(i=1;i<=n;i++)for(j=0;j<=m;j++)f[i][j]=-1; for(i=hash(a),k=1;k<=n;k++)if(i==h[k]){j=k;break;} } return 0; }
时间: 2024-11-06 14:25:16