AC自动机-题目集合
AC自动机-题目集合 模板
如果你想要学习AC自动机,推荐一些学习资料.
学习可以看这篇博客 http://blog.csdn.net/niushuai666/article/details/7002823
或者看看大佬的视频讲解 http://www.bilibili.com/video/av6295004/
下面是一些AC自动机的一些入门题目.和AC代码,先学再做练习.
题目链接: hdu-2222
#include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<set> #include<map> #include<list> #include<queue> #include<deque> #include<stack> #include<string> #include<vector> #include<iostream> #include<algorithm> #include<stdlib.h> #include<time.h> using namespace std; typedef long long LL; const int INF=2e9+1e8; const int MOD=1e9+7; const int MAXSIZE=1e6+5; const double eps=0.0000000001; void fre() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); } #define memst(a,b) memset(a,b,sizeof(a)) #define fr(i,a,n) for(int i=a;i<n;i++) const int MAXNode=5e5+5; struct Aho { int ch[MAXNode][26]; // 多模式字符串 需要构建的 Tire(字典树) int last[MAXNode]; // 统计某一个模式串 (在Tire中MaxNode位置结尾的字符串) 个数, int fail[MAXNode]; //失配指针 int sz,root; int newnode() { memset(ch[sz],-1,sizeof(ch[sz])); last[sz++]=0; return sz-1; } void init() { sz=0; root=newnode(); } void insert(char *s) { int len=strlen(s); int now=root; for(int i=0; i<len; i++) { if(ch[now][s[i]-'a']==-1) ch[now][s[i]-'a']=newnode(); now=ch[now][s[i]-'a']; } last[now]++; } void GetFail()// 如何构建失败指针,还是不太会.所以套 kuangbin 模板 { queue<int>Q; fail[root]=root; for(int i = 0; i < 26; i++) { if(ch[root][i]==-1) ch[root][i]=root; else { fail[ch[root][i]]=root; Q.push(ch[root][i]); } } while(!Q.empty()) { int now=Q.front(); Q.pop(); for(int i=0; i<26; i++) { if(ch[now][i]==-1) ch[now][i]=ch[fail[now]][i]; else { fail[ch[now][i]]=ch[fail[now]][i]; Q.push(ch[now][i]); } } } } int match(char *s) { int len=strlen(s); int now=root; int res=0; for(int i=0; i<len; i++) { now=ch[now][s[i]-'a']; int temp=now; while(temp!=root) { res+=last[temp]; last[temp]=0; temp=fail[temp]; } } return res; } } ac; char str[MAXSIZE]; inline void read(int& ret) //适用于正整数 { char c; ret=0; while((c=getchar())<'0'||c>'9'); while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); } int main(int argc,char *argv[]) { int ncase; read(ncase); while(ncase--) { int n; ac.init(); scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%s",str); ac.insert(str); } ac.GetFail(); scanf("%s",str); printf("%d\n",ac.match(str)); } return 0; } /** http://blog.csdn.net/wr_technology */
鄙人只是存模板,失配指针怎么构建,目前正在学习之中。若想要学习 AC自动机。请点这篇博文。总结的详细。
------------------------------------------ 分割线 ---------------------------------------------------------
上面是kuangbin模板,不太会。因为他在构建fail指针的的时候不是最简单的方法。所以我又找了一另一个代码来学习,这一份就是朴素的方法,不像kuangbin模板优化过,不适合初学者。
#include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<set> #include<map> #include<list> #include<queue> #include<deque> #include<stack> #include<string> #include<vector> #include<iostream> #include<algorithm> #include<stdlib.h> #include<time.h> using namespace std; typedef long long LL; const int INF=2e9+1e8; const int MOD=1e9+7; const int MAXSIZE=1e6+5; const double eps=0.0000000001; void fre() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); } #define memst(a,b) memset(a,b,sizeof(a)) #define fr(i,a,n) for(int i=a;i<n;i++) const int MAXNode=5e5+5; struct Aho { int ch[MAXNode][26]; // 多模式字符串 需要构建的 Tire(字典树) int last[MAXNode]; // 统计某一个模式串 (在Tire中MaxNode位置结尾的字符串) 个数, int fail[MAXNode]; //失配指针 int sz,root; int newnode() { memset(ch[sz],-1,sizeof(ch[sz])); last[sz++]=0; return sz-1; } void init() { sz=0; root=newnode(); } void insert(char *s) { int len=strlen(s); int now=root; for(int i=0; i<len; i++) { if(ch[now][s[i]-'a']==-1) ch[now][s[i]-'a']=newnode(); now=ch[now][s[i]-'a']; } last[now]++; } void GetFail()// { queue<int>Q; Q.push(root); while(!Q.empty()) { int now=Q.front(); Q.pop(); for(int i=0;i<26;i++) { if(ch[now][i]!=-1) { if(now==root) fail[ch[now][i]]=root; else { int temp=fail[now]; while(temp&&ch[temp][i]==-1) temp=fail[temp]; fail[ch[now][i]]=ch[temp][i]; } Q.push(ch[now][i]); } } } return ; } int match(char *s) { int len=strlen(s); int now=root,temp; int res=0; for(int i=0; i<len; i++) { while(now&&ch[now][s[i]-'a']==-1) now=fail[now];temp=now=ch[now][s[i]-'a']; while(temp!=root) { res+=last[temp]; last[temp]=0; temp=fail[temp]; } } return res; } } ac; char str[MAXSIZE]; inline void read(int& ret) { char c; ret=0; while((c=getchar())<'0'||c>'9'); while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); } int main(int argc,char *argv[]) { int ncase; read(ncase); while(ncase--) { int n; ac.init(); scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%s",str); ac.insert(str); } ac.GetFail(); scanf("%s",str); printf("%d\n",ac.match(str)); } return 0; } /** http://blog.csdn.net/wr_technology */
------------------------------------------------------------------------------------------------------------------------------------------------------------
下面是 hdu-2896
#include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<set> #include<map> #include<list> #include<queue> #include<deque> #include<stack> #include<string> #include<vector> #include<iostream> #include<algorithm> #include<stdlib.h> #include<time.h> using namespace std; typedef long long LL; const int INF=2e9+1e8; const int MOD=1e9+7; const int MAXSIZE=1e6+5; const double eps=0.0000000001; void fre() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); } #define memst(a,b) memset(a,b,sizeof(a)) #define fr(i,a,n) for(int i=a;i<n;i++) const int MAXNode=5e5+5; int ans[10005][505],cnt[505]; struct Aho { int ch[100000][128]; // 多模式字符串 需要构建的 Tire(字典树) int last[MAXNode]; // 统计某一个模式串 (在Tire中MaxNode位置结尾的字符串) 个数, int fail[MAXNode]; //失配指针 int sz,root; int newnode() { memset(ch[sz],-1,sizeof(ch[sz])); last[sz++]=0; return sz-1; } void init() { sz=0; root=newnode(); } void insert(char *s,int id) { int now=root; for(int i=0; s[i]!='\0' ; i++) { if(ch[now][(int)s[i]]==-1) ch[now][(int)s[i]]=newnode(); now=ch[now][(int)s[i]]; } last[now]=id; } void GetFail() { queue<int>Q; Q.push(root); while(!Q.empty()) { int now=Q.front(); Q.pop(); for(int i=0; i<128; i++) { if(ch[now][i]!=-1) { if(now==root) fail[ch[now][i]]=root; else { int temp=fail[now]; while(temp&&ch[temp][i]==-1) temp=fail[temp]; fail[ch[now][i]]=ch[temp][i]; } Q.push(ch[now][i]); } } } return ; } void match(char *s,int id) { int flag[550]; memset(flag,0,sizeof(flag)); int now=root,temp; for(int i=0; s[i]!='\0'; i++) { while(now&&ch[now][(int)s[i]]==-1) now=fail[now]; temp=now=ch[now][(int)s[i]]; while(temp!=root&&flag[last[temp]]==0) { if(last[temp]) { ans[id][cnt[id]++]=last[temp]; flag[last[temp]]=1; } temp=fail[temp]; } if(cnt[id]>=3) break; } return ; } } ac; char str[MAXSIZE]; void print(int m) { int sum=0; for(int i=1; i<=m; i++) { if(!cnt[i]) continue; printf("web %d:",i); for(int j=0; j<cnt[i]; j++) printf(" %d",ans[i][j]); printf("\n"); sum++; } printf("total: %d\n",sum); } int main(int argc,char *argv[]) { int n,m; scanf("%d",&n); getchar(); memset(cnt,0,sizeof(cnt)); ac.init(); for(int i=1; i<=n; i++) { gets(str); ac.insert(str,i); } ac.GetFail(); scanf("%d",&m); getchar(); for(int j=1; j<=m; j++) { scanf("%s",str); ac.match(str,j); sort(ans[j],ans[j]+cnt[j]); } print(m); return 0; }
-----------------------------------------------------------------------------------------------------------------------
#include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<set> #include<map> #include<list> #include<queue> #include<deque> #include<stack> #include<string> #include<vector> #include<iostream> #include<algorithm> #include<stdlib.h> #include<time.h> using namespace std; typedef long long LL; const int INF=2e9+1e8; const int MOD=1e9+7; const int MAXSIZE=1e6+5; const double eps=0.0000000001; void fre() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); } #define memst(a,b) memset(a,b,sizeof(a)) #define fr(i,a,n) for(int i=a;i<n;i++) const int MAXNode=5e6+5; struct Aho { int ch[MAXNode][26],fail[MAXNode],last[MAXNode],root,sz; int newnode() { memset(ch[sz],-1,sizeof(ch[sz])); last[sz++]=0; return sz-1; } void init() { sz=0; root=newnode(); } void insert(char *s) { int now=root; for(int i=0; s[i]!='\0'; i++) { int id=(int)(s[i]-'a'); if(ch[now][id]==-1) ch[now][id]=newnode(); now=ch[now][id]; } last[now]=1; } void GetFail() { queue<int>Q; fail[root]=root; Q.push(root); while(!Q.empty()) { int now=Q.front(); Q.pop(); for(int i=0; i<26; i++) { if(now==root) { if(ch[now][i]==-1) ch[now][i]=root; else fail[ch[now][i]]=root,Q.push(ch[now][i]); } else { if(ch[now][i]==-1) ch[now][i]=ch[fail[now]][i]; else fail[ch[now][i]]=ch[fail[now]][i],Q.push(ch[now][i]); } } } } bool match(char *s) { int now=root; for(int i=0; s[i]!='\0'; i++) { now=ch[now][(int)(s[i]-'a')]; if(last[now]) return true; } return false; } } ac; char str[MAXSIZE]; int main() { int n; cin>>n; ac.init(); for(int i=0; i<n; i++) { scanf("%s",str); ac.insert(str); } scanf("%s",str); ac.GetFail(); if(ac.match(str)) cout<<"YES"<<endl; else cout<<"NO"<<endl; return 0; }
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步