首页 > 代码库 > AC自动机(BZOJ1030)

AC自动机(BZOJ1030)

#include <cstdio>#include <queue>#include <cstring>using namespace std;  const int mo=10007;    int cnt;    int trie[6101][31];  int val[6101];  int f[6101],last[6101];  int n,m;  char st[61][101];  int tmp[101];  int dp[101][6101][2];  int newnode(){      return(++cnt);  }  void ins(int a[],int len){      int t=0;      for (int i=1;i<=len;i++){        if (trie[t][a[i]]==0) t=trie[t][a[i]]=newnode();else                             t=trie[t][a[i]];        }    val[t]=1;  }    queue <int> q;  void getfail(){      for (int i=1;i<=26;i++)         if (trie[0][i]){          q.push(trie[0][i]);        f[trie[0][i]]=last[trie[0][i]]=0;          }          while (!q.empty()){      int t=q.front();q.pop();      for (int i=1;i<=26;i++){          int u=trie[t][i];          if (u==0) {trie[t][i]=trie[f[t]][i];continue;}          q.push(u);          f[u]=trie[f[t]][i];          if (val[f[u]]) last[u]=f[u]/*,val[u]=1*/;else last[u]=last[f[u]];      }        }    }  int main(){      scanf("%d%d",&n,&m);      for (int i=1;i<=n;i++){        scanf("%s",&st[i]);      int le=strlen(st[i]);      for (int j=1;j<=le;j++) tmp[j]=st[i][j-1]-A+1;      ins(tmp,le);        }        getfail();        dp[0][0][0]=1;    for (int i=0;i<m;i++)      for (int j=0;j<=cnt;j++){        if (dp[i][j][0]){          for (int k=1;k<=26;k++)           if (val[trie[j][k]])            dp[i+1][trie[j][k]][1]+=dp[i][j][0],dp[i+1][trie[j][k]][1]%=mo;else            dp[i+1][trie[j][k]][0]+=dp[i][j][0],dp[i+1][trie[j][k]][0]%=mo;        }        if (dp[i][j][1]){          for (int k=1;k<=26;k++)            dp[i+1][trie[j][k]][1]+=dp[i][j][1],dp[i+1][trie[j][k]][1]%=mo;            }    }            int ans=0;    for (int i=0;i<=cnt;i++)      ans+=dp[m][i][1],ans%=mo;        printf("%d\n",ans);    }

自动机中一个节点对应了多个串,如此题中虽在字典树中非叶子节点,但可能对应了一个串

例:abab,ba,在到达找寻aba时实际已找到ba

AC自动机(BZOJ1030)