对于AC自动机的理解,转载注明出自bestsort.cn 说得贼棒,图文并茂
自己的模板
1 int trie[maxn][27]; 2 int cntword[maxn]; 3 int fail[maxn]; 4 int cnt=1; 5 void add(char *s){ 6 it root = 0,l=strlen(s); 7 for(it i=0;i<l;i++){ 8 int next =s[i]-'A'; 9 if(!trie[root][next]) 10 trie[root][next] = cnt++; 11 root = trie[root][next]; 12 } 13 cntword[root]++;//这里没有重复 14 } 15 void getFail(){ 16 queue <int>q; 17 for(it i=0;i<26;i++){ 18 if(trie[0][i]){ 19 fail[trie[0][i]] = 0; 20 q.push(trie[0][i]); 21 } 22 } 23 while(!q.empty()){ 24 int now = q.front(); 25 q.pop(); 26 for(int i=0;i<26;i++){ 27 if(trie[now][i]){ 28 fail[trie[now][i]] = trie[fail[now]][i]; 29 q.push(trie[now][i]); 30 } 31 else 32 trie[now][i] = trie[fail[now]][i]; 33 } 34 } 35 } 36 int query(char *s){ 37 int now = 0,ans = 0,l=strlen(s); 38 for(it i=0;i<l;i++){ 39 if(s[i]<'A' ||s[i]>'Z'){now=0;continue;}//如果字符串有不是A~Z的now归零 40 now = trie[now][s[i]-'A']; 41 for(it j=now;j && cntword[j]!=-1;j=fail[j]){ 42 cntword[j]=-1; 43 ans++;//出现过的字符串,标记 44 } 45 } 46 return ans; 47 }
hdu2896 病毒侵袭(模板题)
题意:
输入n个字符串(n<=500),这n个字符串是指病毒,字符串长度不超过200,字符是ASCII码可见字符.
给m个字符串(长度不超过1e5)表示网址(m<=1000),说这个网址会有多少病毒,最后统计有多少带病毒的网址
样例输入 样例输出
思路:
因为字符是ASCII码可见字符,所以字符范围128,tire长度[200*500][128],用cntword标记病毒序号。
这题hduG++,mle到自闭,然后换了C++就过了,毒毒毒毒瘤。
1 #include<iostream> 2 #include<map> 3 #include<set> 4 #include<queue> 5 #include<stdio.h> 6 #include<string.h> 7 using namespace std; 8 #define ll long long 9 #define ull unsigned long long 10 #define il inline 11 #define it register int 12 #define inf 0x3f3f3f3f 13 #define lowbit(x) (x)&(-x) 14 #define pii pair<int,int> 15 #define mak(n,m) make_pair(n,m) 16 #define mem(a,b) memset(a,b,sizeof(a)) 17 #define mod 998244353 18 const int maxn=1e5+10; 19 int trie[maxn][128]; 20 int cntword[maxn]; 21 int fail[maxn]; 22 int cnt=0,tot=0,num=1; 23 map<char,int>mp; 24 void add(char *s,int num1){ 25 it root = 0,l=strlen(s); 26 for(it i=0;i<l;i++){ 27 int next =mp[s[i]]; 28 if(next==0){next=num; 29 mp[s[i]]=num++; 30 } 31 if(!trie[root][next]) 32 trie[root][next] = ++cnt; 33 root = trie[root][next]; 34 } 35 cntword[root]=num1; 36 } 37 void getFail(){ 38 queue <int>q; 39 for(it i=1;i<=num;i++){ 40 if(trie[0][i]){ 41 fail[trie[0][i]] = 0; 42 q.push(trie[0][i]); 43 } 44 } 45 while(!q.empty()){ 46 int now = q.front(); 47 q.pop(); 48 for(int i=1;i<=num;i++){ 49 if(trie[now][i]){ 50 fail[trie[now][i]] = trie[fail[now]][i]; 51 q.push(trie[now][i]); 52 } 53 else 54 trie[now][i] = trie[fail[now]][i]; 55 } 56 } 57 } 58 void query(char *s,int num1){ 59 int now = 0,ans = 0,l=strlen(s); 60 set<int>st; 61 for(it i=0;i<l;i++){ 62 now = trie[now][mp[s[i]]]; 63 for(it j=now;j && cntword[j]!=-1;j=fail[j]){ 64 st.insert(cntword[j]); 65 //cntword[j] = -1; 66 } 67 } 68 if(st.size()){tot++; 69 printf("web %d:",num1); 70 for(auto &i:st){ 71 printf(" %d",i); 72 } 73 printf("\n"); 74 } 75 } 76 char s[10010],ss[210]; 77 int main(){ 78 int n,m;mem(cntword,-1); 79 scanf("%d",&n); 80 for(it i=1;i<=n;i++){ 81 scanf("%s",ss); 82 add(ss,i); 83 } 84 getFail(); 85 scanf("%d",&m); 86 for(it i=1;i<=m;i++){ 87 scanf("%s",s); 88 query(s,i); 89 } 90 printf("total: %d\n",tot); 91 return 0; 92 }
hdu3065 病毒侵袭持续中(模板题)
题意:
给n个A~Z字符串,字符串长度不超过50(n<=1000),再给一个字符串长度2000000的,里面的字符是ASCII码可见字符,问n出现过几次
样例输入 样例输出
3 AA: 2
AA CC: 1
BB
CC
ooxxCC%dAAAoen....END
思路:
模板套一套,但问题是tire[50*1000][26]是re…,要[1e5][26]
1 #include<iostream> 2 #include<map> 3 #include<set> 4 #include<queue> 5 #include<stdio.h> 6 #include<string.h> 7 using namespace std; 8 #define ll long long 9 #define ull unsigned long long 10 #define il inline 11 #define it register int 12 #define inf 0x3f3f3f3f 13 #define lowbit(x) (x)&(-x) 14 #define pii pair<int,int> 15 #define mak(n,m) make_pair(n,m) 16 #define mem(a,b) memset(a,b,sizeof(a)) 17 #define mod 998244353 18 const int maxn=1e5+10; 19 int trie[maxn][27]; 20 int cntword[maxn]; 21 int fail[maxn]; 22 int cnt=0,tot=0,n; 23 void add(char *s,int num1){ 24 it root = 0,l=strlen(s); 25 for(it i=0;i<l;i++){ 26 int next =s[i]-'A'; 27 if(!trie[root][next]) 28 trie[root][next] = ++cnt; 29 root = trie[root][next]; 30 } 31 cntword[root]=num1; 32 } 33 void getFail(){ 34 queue <int>q; 35 for(it i=0;i<26;i++){ 36 if(trie[0][i]){ 37 fail[trie[0][i]] = 0; 38 q.push(trie[0][i]); 39 } 40 } 41 while(!q.empty()){ 42 int now = q.front(); 43 q.pop(); 44 for(int i=0;i<26;i++){ 45 if(trie[now][i]){ 46 fail[trie[now][i]] = trie[fail[now]][i]; 47 q.push(trie[now][i]); 48 } 49 else 50 trie[now][i] = trie[fail[now]][i]; 51 } 52 } 53 } 54 char s1[2000010],ss[1010][55]; 55 void query(char *s){ 56 int now = 0,ans = 0,l=strlen(s); 57 int numm[1010]={0}; 58 for(it i=0;i<l;i++){ 59 if(s[i]<'A' ||s[i]>'Z'){now=0;continue;} 60 now = trie[now][s[i]-'A']; 61 for(it j=now;j && cntword[j]!=-1;j=fail[j]){ 62 numm[cntword[j]]++; 63 //cout<<cntword[j]<<endl; 64 } 65 } 66 for(it i=1;i<=n;i++){ 67 if(numm[i]==0){continue;} 68 printf("%s: %d\n",ss[i],numm[i]); 69 } 70 } 71 72 int main(){ 73 while(~scanf("%d",&n)){ 74 mem(cntword,-1);mem(trie,0); 75 for(it i=1;i<=n;i++){ 76 scanf("%s",ss[i]); 77 add(ss[i],i); 78 } 79 getFail(); 80 scanf("%s",s1); 81 query(s1); 82 } 83 return 0; 84 }
对了对了还有一个hdu2222,我用tire树莽过的题
这里就贴一个代码吧
1 #include<queue> 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 #include<cmath> 8 #include<string> 9 #include<vector> 10 #include<functional> 11 #pragma warning(disable:4996) 12 using namespace std; 13 const int maxn = 1000010; 14 #define inf 0x3f3f3f3f 15 #define mem(k,b) memset(k,b,sizeof(k)) 16 #define ll long long 17 char s[maxn]; 18 char ss[55]; 19 int k = 1, t, n; 20 int g[240000][26] = { 0 }, vis[240000] = { 0 }; 21 inline void insert(char *w){ 22 int p = 0, l = strlen(w); 23 for (int i = 0; i < l; i++){ 24 int c = w[i] - 'a'; 25 if (!g[p][c]){ 26 g[p][c] = k++; 27 } 28 p = g[p][c]; 29 } 30 vis[p]++; 31 return; 32 } 33 inline int search(char *w){ 34 int l = strlen(w); 35 int sum = 0; 36 for (int j = 0; j < l; j++){ 37 int p = 0; 38 for (int i = j; i < j + 50; i++){ 39 if (i == l){ 40 break; 41 } 42 int c = w[i] - 'a'; 43 if (!g[p][c]){ 44 break; 45 } 46 p = g[p][c]; 47 if (vis[p]){ 48 sum += vis[p]; 49 vis[p] = 0; 50 } 51 } 52 } 53 return sum; 54 } 55 int main() 56 { 57 scanf("%d", &t); 58 while (t--){ 59 k = 1; mem(vis, 0); mem(g, 0); 60 scanf("%d", &n); 61 getchar(); 62 for (int i = 0; i < n; i++){ 63 gets(ss); 64 insert(ss); 65 } 66 gets(s); 67 printf("%d\n", search(s)); 68 69 } 70 return 0; 71 }