1 5 she he say shr her yasherhs
3
#include <cstdio> #include <cstring> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int maxn=1000010; const int bsz=26; typedef long long ll; char txt[1000010]; bool vis[510]; int ans; struct Trie { int ch[maxn][bsz],val[maxn],sz,cnt[maxn]; // ch存Trie val-节点对应的单词 cnt-节点结尾单词个数 int f[maxn],last[maxn];//f-失配指针 last-后缀链接 int newnode() { val[sz]=0; cnt[sz]=0; memset(ch[sz],-1,sizeof ch[sz]); return sz++; } void init() { sz=0; newnode(); } int idx(char c) // 取c的标号 具体看字符为什么 { return c-'a'; } void Insert(char *st,int id) { int u=0,n=strlen(st),c,i; for(i=0;i<n;i++) { c=idx(st[i]); if(ch[u][c]==-1) ch[u][c]=newnode(); u=ch[u][c]; } val[u]=id; cnt[u]++; } void build() { int u=0,v,i; queue<int> q; f[0]=0; for(i=0;i<bsz;i++) { v=ch[u][i]; if(v==-1) ch[u][i]=0; else { f[v]=0; q.push(v); } } while(!q.empty()) { u=q.front(); q.pop(); last[u]=val[f[u]]?f[u]:last[f[u]]; for(i=0;i<bsz;i++) { v=ch[u][i]; if(v==-1) ch[u][i]=ch[f[u]][i]; // 将NULL变为有意义 沿着父亲失配指针走第一个有意义的节点 else { f[v]=ch[f[u]][i]; q.push(v); } } } } bool Find(char *st,int m,int id) { int n=strlen(st),i,u=0,c,p,flag=0; //memset(vis,0,sizeof vis); 可标记哪些单词出现过 同样的单词只标记一个 for(i=0;i<n;i++) { c=idx(st[i]); u=ch[u][c]; p=val[u]?u:last[u]; while(p) { //vis[val[p]]=true; if(val[p]){ ans+=cnt[p]; cnt[p]=0; } // 加上该串出现次数 清零 避免重复计数 flag=1; p=last[p]; } } if(!flag) return false; // for(i=1;i<=m;i++) // if(vis[i]) // printf(" %d",i); // putchar('\n'); return true; } } ac; int main() { int i,n,m,tot; scanf("%d",&tot); while(tot--) { scanf("%d",&n); ac.init(); for(i=1;i<=n;i++) { scanf("%s",txt); ac.Insert(txt,i); } ac.build(); ans=0; scanf("%s",txt); ac.Find(txt,n,i); printf("%d\n",ans); } return 0; } /* 1 5 she he say her her yasherhs */
hdu 2222 Keywords Search(AC自动机入门)
原文:http://blog.csdn.net/tobewhatyouwanttobe/article/details/46405065