首页 > 代码库 > HDU 2222 最简单的AC自动机套模板应用
HDU 2222 最简单的AC自动机套模板应用
HDU 2222 题意:给出N(N<=10,000)个单词,每个单词长度不超过50。再给出一个字符串S,字符串长度不超过1,000,000。问有多少个单词出现在了字符串S中。(单词可能重复,单词在S中允许重叠)
我们在val[]数组中记录重复的个数
因为在主串对他进行匹配时,匹配到一次后这个重复次数就不应该继续添加了,所以在query中val[]要对它进行清零操作
#include <cstdio>#include <cstring>#include <queue>using namespace std;#define N 500005char str[1000005];struct AC{ int ch[N][26],fail[N],val[N],last[N],tmp,root; int newnode(){ val[tmp]=0; memset(ch[tmp],0,sizeof(ch[tmp])); return tmp++; } void init(){ tmp=0; root=newnode(); } void add(char *s){ int len=strlen(s); int now=root; for(int i=0;i<len;i++){ int &k=ch[now][s[i]-‘a‘]; if(!k) k=newnode(); now=k; } val[now]++; } void get_fail(){ fail[root]=root; queue<int> q; for(int i=0;i<26;i++){ int v=ch[root][i]; if(v) fail[v]=last[v]=0,q.push(v); } while(!q.empty()){ int now=q.front(); q.pop(); for(int i=0;i<26;i++){ int v=ch[now][i]; if(!v) ch[now][i]=ch[fail[now]][i]; else{ fail[v]=ch[fail[now]][i]; last[v]=val[fail[v]]?fail[v]:last[fail[v]]; q.push(v); } } } } int query(char *str){ int len=strlen(str); int now=root,ret=0; for(int i=0;i<len;i++){ now=ch[now][str[i]-‘a‘]; int k=now; while(k!=root&&val[k]){//这是要循环到找到fail值为root的时候或者找到匹配的字符串的时候,否则一直向前找fail值, ret+=val[k]; val[k]=0; k=last[k]; } } return ret; }}ac;int main(){ int T,n; scanf("%d",&T); while(T--){ ac.init(); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s",str); ac.add(str); } ac.get_fail(); scanf("%s",str); int ans=ac.query(str); printf("%d\n",ans); } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。