HDU-2222 Keywords Search(AC自动机--模板题)
题目大意:统计一共出现了多少次模板串。
题目分析:AC自动机的模板题。不过这题有坑,相同的模板串不能只算一次。
代码如下:
# include<iostream> # include<cstdio> # include<queue> # include<map> # include<string> # include<cstring> # include<algorithm> using namespace std; const int N=10000; int ch[N*50+5][26]; int val[N*50+5]; int last[N*50+5]; int f[N*50+5]; bool mark[N*50+5]; map<string,int>mp; string str[N+5]; struct AC { int cnt,res; void init() { res=cnt=0; memset(ch,0,sizeof(ch)); memset(val,0,sizeof(val)); memset(mark,false,sizeof(mark)); } int idx(char c) { return c-'a'; } void insert(string str,int v) { int u=0; int n=str.size(); for(int i=0;i<n;++i){ int c=idx(str[i]); if(!ch[u][c]) ch[u][c]=++cnt; u=ch[u][c]; } val[u]=v; } void getFail() { queue<int>q; f[0]=0; for(int i=0;i<26;++i){ int u=ch[0][i]; if(!u) continue; f[u]=0; q.push(u); last[u]=0; } while(!q.empty()) { int r=q.front(); q.pop(); for(int i=0;i<26;++i){ int u=ch[r][i]; if(!u){ ch[r][i]=ch[f[r]][i]; }else{ q.push(u); int v=f[r]; while(v&&!ch[v][i]) v=f[v]; f[u]=ch[v][i]; last[u]=val[f[u]]?f[u]:last[f[u]]; } } } } void ac(string str) { int n=str.size(); int j=0; for(int i=0;i<n;++i){ int c=idx(str[i]); j=ch[j][c]; if(val[j]) print(j); else if(last[j]) print(last[j]); } } void print(int u) { if(u){ if(!mark[val[u]]) res+=mp[str[val[u]]]; mark[val[u]]=true; print(last[u]); } } int getResult() { return res; } }ac; char s[N*100+5]; int main() { int T,n; scanf("%d",&T); while(T--) { mp.clear(); scanf("%d",&n); ac.init(); for(int i=1;i<=n;++i){ cin>>str[i]; ++mp[str[i]]; ac.insert(str[i],i); } scanf("%s",s); ac.getFail(); ac.ac(s); printf("%d\n",ac.getResult()); } return 0; }