AC自动机模板
经典例题
Keywords Search HDU - 2222
【求目标串中出现了几个模式串】
【(注意:模式串可能会重复)】
模板:
1 const int maxn=26; 2 struct Trie 3 { 4 int next[500010][maxn]; 5 int fail[500010],end[500010]; 6 int root,L; 7 int newnode() //初始化 8 { 9 for(int i=0;i<26;i++) 10 next[L][i]=-1; 11 end[L++]=0; 12 return L-1; 13 } 14 15 void init()//初始化 16 { 17 L=0; 18 root=newnode(); 19 } 20 void insert(char s[])//构造树trie 21 { 22 int len=strlen(s); 23 int now=root; 24 for(int i=0;i<len;i++) 25 { 26 if(next[now][s[i]-'a']==-1) 27 next[now][s[i]-'a']=newnode(); 28 now=next[now][s[i]-'a']; 29 } 30 end[now]++; 31 } 32 33 void build()//构造失败指针 34 { 35 queue<int>Q; 36 fail[root]=root; 37 for(int i=0;i<26;i++) 38 if(next[root][i]==-1) 39 next[root][i]=root; 40 else 41 { 42 fail[next[root][i]]=root; 43 Q.push(next[root][i]); 44 } 45 while(!Q.empty()) 46 { 47 int now=Q.front(); 48 Q.pop(); 49 for(int i=0;i<26;i++) 50 if(next[now][i]==-1) 51 next[now][i]=next[fail[now]][i]; 52 else 53 { 54 fail[next[now][i]]=next[fail[now]][i]; 55 Q.push(next[now][i]); 56 } 57 58 } 59 } 60 61 void query(char buf[])//查询 62 { 63 int len=strlen(buf); 64 int now=root; 65 int sum=0; 66 for(int i=0;i<len;i++) 67 { 68 now = next[now][buf[i]-'a']; 69 int temp = now; 70 while(temp != root) 71 { 72 73 sum+=end[temp]; 74 end[temp]=0;//避免重复计算 75 temp = fail[temp]; 76 } 77 } 78 printf("%d ",sum); 79 } 80 };
病毒侵袭 HDU - 2896
【统计目标串中模式串的个数】
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #include<cmath> 8 #include<string> 9 #include<map> 10 #define LL long long 11 using namespace std; 12 const int maxn=128;//模板部分 13 struct Trie 14 { 15 int next[210*500][maxn]; 16 int fail[210*500],end[210*500]; 17 int root,L; 18 int newnode() //初始化 19 { 20 for(int i=0;i<128;i++) 21 next[L][i]=-1; 22 end[L++]=-1; 23 return L-1; 24 } 25 26 void init()//初始化 27 { 28 L=0; 29 root=newnode(); 30 } 31 void insert(char s[],int id)//构造树trie 32 { 33 int len=strlen(s); 34 int now=root; 35 for(int i=0;i<len;i++) 36 { 37 if(next[now][s[i]]==-1) 38 next[now][s[i]]=newnode(); 39 now=next[now][s[i]]; 40 } 41 end[now]=id;//记录单词的id 42 } 43 44 void build()//构造失败指针 45 { 46 queue<int>Q; 47 fail[root]=root; 48 for(int i=0;i<128;i++) 49 if(next[root][i]==-1) 50 next[root][i]=root; 51 else 52 { 53 fail[next[root][i]]=root; 54 Q.push(next[root][i]); 55 } 56 while(!Q.empty()) 57 { 58 int now=Q.front(); 59 Q.pop(); 60 for(int i=0;i<128;i++) 61 if(next[now][i]==-1) 62 next[now][i]=next[fail[now]][i]; 63 else 64 { 65 fail[next[now][i]]=next[fail[now]][i]; 66 Q.push(next[now][i]); 67 } 68 69 } 70 } 71 72 73 bool vis[510]; 74 bool query(char buf[],int n,int id)//查询 75 { 76 int len=strlen(buf); 77 int now=root; 78 memset(vis,0,sizeof(vis)); 79 bool flag=false; 80 for(int i=0;i<len;i++) 81 { 82 now = next[now][buf[i]]; 83 int temp = now; 84 while(temp != root) 85 { 86 if(end[temp] != -1) 87 { 88 vis[end[temp]] = true; 89 flag = true; 90 } 91 temp = fail[temp]; 92 } 93 } 94 if(!flag)return false; 95 printf("web %d:",id); 96 for(int i = 1;i <= n;i++) 97 if(vis[i]) 98 printf(" %d",i); 99 printf(" "); 100 return true; 101 } 102 }; 103 char str1[205]; 104 char str2[10010]; 105 Trie ac; 106 int main() 107 { 108 int n,m; 109 while(scanf("%d",&n) != EOF) 110 { 111 ac.init(); 112 for(int i = 1;i <= n;i++) 113 { 114 scanf("%s",str1); 115 ac.insert(str1,i); 116 } 117 ac.build(); 118 int ans = 0; 119 scanf("%d",&m); 120 for(int i = 1;i <= m;i++) 121 { 122 scanf("%s",str2); 123 if(ac.query(str2,n,i)) 124 ans++; 125 } 126 printf("total: %d ",ans); 127 } 128 return 0; 129 }
病毒侵袭持续中 HDU - 3065
【思路:和病毒侵袭 HDU - 2896 这题差不多,只是多了一个计数。】
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #include<cmath> 8 #include<string> 9 #include<map> 10 11 using namespace std; 12 #define int long long 13 const int maxn=128; 14 15 char str1[1010][100]; 16 char str2[2000005]; 17 18 char STR[1003][66]; 19 char SSS[2000100]; 20 struct Trie{ 21 int next[2010*50][maxn]; 22 int fail[2010*50],end[2010*50]; 23 int root,L; 24 int newnode() //初始化 25 { 26 for(int i=0;i<128;i++) 27 next[L][i]=-1; 28 end[L++]=-1; 29 return L-1; 30 } 31 32 void init()//初始化 33 { 34 L=0; 35 root=newnode(); 36 } 37 void insert(char s[],int id)//构造树trie 38 { 39 int len=strlen(s); 40 int now=root; 41 for(int i=0;i<len;i++) 42 { 43 if(next[now][s[i]]==-1) 44 next[now][s[i]]=newnode(); 45 now=next[now][s[i]]; 46 } 47 end[now]=id;//记录单词的id 48 } 49 50 void build()//构造失败指针 51 { 52 queue<int>Q; 53 fail[root]=root; 54 for(int i=0;i<128;i++) 55 if(next[root][i]==-1) 56 next[root][i]=root; 57 else 58 { 59 fail[next[root][i]]=root; 60 Q.push(next[root][i]); 61 } 62 while(!Q.empty()) 63 { 64 int now=Q.front(); 65 Q.pop(); 66 for(int i=0;i<128;i++) 67 if(next[now][i]==-1) 68 next[now][i]=next[fail[now]][i]; 69 else 70 { 71 fail[next[now][i]]=next[fail[now]][i]; 72 Q.push(next[now][i]); 73 } 74 75 } 76 } 77 78 79 int vis[1666];//记录出现的次数 80 void query(char buf[],int n)//查询 81 { 82 int len=strlen(buf); 83 int now=root; 84 memset(vis,0,sizeof(vis)); 85 bool flag=false; 86 for(int i=0;i<len;i++) 87 { 88 now = next[now][buf[i]]; 89 int temp = now; 90 while(temp != root) 91 { 92 if(end[temp] != -1) 93 { 94 vis[end[temp]]++; 95 flag = true; 96 } 97 temp = fail[temp]; 98 } 99 } 100 if(flag ){ 101 for(int i=1;i<=n;i++){ 102 if(vis[i]){ 103 printf("%s: %lld ",STR[i],vis[i]); 104 } 105 } 106 } 107 return ; 108 109 110 } 111 }AC; 112 113 signed main(){ 114 int n; 115 116 while(~scanf("%lld",&n)){ 117 118 AC.init(); 119 for(int i=1;i<=n;i++){ 120 scanf("%s",STR[i]); 121 AC.insert(STR[i],i); 122 } 123 AC.build(); 124 scanf("%s",SSS); 125 AC.query(SSS,n); 126 } 127 return 0; 128 }