3065 【AC自動機】
阿新 • • 發佈:2018-12-16
在一個串中找出給定子串出現的次數
#include<bits/stdc++.h> #define cl(a) memset(a,0,sizeof(a)) #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; char s[1005][150]; struct Trie { int nxt[1005*55][128],fail[1005*55],ends[1005*55]; int root,L; int newnode() { rep(i,0,127) nxt[L][i]=-1; fail[L]=-1; ends[L++]=-1; return L-1; } void init() { L=0; root = newnode(); } void ins(char s[],int id) { int len = strlen(s); int now = root; rep(i,0,len-1) { if(nxt[now][s[i]]==-1) { nxt[now][s[i]]=newnode(); } now=nxt[now][s[i]]; } ends[now]=id; } void build() { queue<int>q; fail[root]=root; rep(i,0,127) { if(nxt[root][i]==-1) { nxt[root][i] = root; } else { fail[nxt[root][i]]=root; q.push(nxt[root][i]); } } while(!q.empty()) { int now = q.front(); q.pop(); rep(i,0,127) { if(nxt[now][i]==-1) { nxt[now][i]=nxt[fail[now]][i]; } else { fail[nxt[now][i]]=nxt[fail[now]][i]; q.push(nxt[now][i]); } } } } int num[1010]; void query(char buf[],int n) { int len = strlen(buf); int now =root; for(int i=0; i<=n; i++) { num[i]=0; } //bool flag=false; rep(i,0,len-1) { now = nxt[now][buf[i]]; int tmp = now; while(tmp!=root) { if(ends[tmp]!=-1) { num[ends[tmp]]++; //flag=true; } tmp=fail[tmp]; } } rep(i,0,n-1) { if(num[i]>0) printf("%s: %d\n",s[i],num[i]); } } }; char buf[2000005]; Trie ac; int main() { int n; while(scanf("%d",&n)!=EOF) { ac.init(); for(int i=0; i<n; i++) { scanf("%s",s[i]); ac.ins(s[i],i); } ac.build(); scanf("%s",buf); ac.query(buf,n); } return 0; }