BZOJ4060 : [Cerc2012]Word equations

首先通过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;
}

  

原文地址:https://www.cnblogs.com/clrs97/p/4599296.html