BZOJ2061 : Country

记忆化搜索,设$f[i][j]$表示符号$i$一开始kmp指针为$j$,中间匹配了多少次,$g[i][j]$则表示匹配结束后kmp指针的位置。

时间复杂度$O(nl^2)$。

 

#include<cstdio>
#include<cstring>
const int N=26,M=105,P=10000;
int n,m,F,i,j,len[N],nxt[M],f[N][M],g[N][M],v[N][M];char s[M],a[N][M];
inline void up(int&x,int y){x+=y;if(x>=P)x-=P;}
void dp(int x,int y){
  if(v[x][y])return;
  int i,j;
  for(i=0,j=y;i<len[x];i++)if(a[x][i]>='a'){
    while(j&&s[j+1]!=a[x][i])j=nxt[j];
    if(s[j+1]==a[x][i])j++;
    if(j==m)up(f[x][y],1),j=nxt[j];
  }else{
    int k=a[x][i]-'A';
    dp(k,j),up(f[x][y],f[k][j]),j=g[k][j];
  }
  v[x][y]=1,g[x][y]=j;
}
int main(){
  scanf("%d%s",&n,s),F=s[0]-'A';
  while(n--){
    scanf("%s",s),m=strlen(s);
    len[i=s[0]-'A']=m-2;
    for(j=2;j<m;j++)a[i][j-2]=s[j];
  }
  scanf("%s",s+1),m=strlen(s+1);
  for(i=2;i<=m;nxt[i++]=j){
    while(j&&s[j+1]!=s[i])j=nxt[j];
    if(s[j+1]==s[i])j++;
  }
  dp(F,0);
  return printf("%d",f[F][0]),0;
}

  

posted @ 2016-02-19 20:43  Claris  阅读(596)  评论(0编辑  收藏  举报