1. 程式人生 > >hdu3065 病毒侵襲持續中 AC自動機入門題 N(N <= 1000)個長度不大於50的模式串(保證所有的模式串都不相同), 一個長度不大於2000000的待匹配串,求模式串在待匹配串中的出現次數。

hdu3065 病毒侵襲持續中 AC自動機入門題 N(N <= 1000)個長度不大於50的模式串(保證所有的模式串都不相同), 一個長度不大於2000000的待匹配串,求模式串在待匹配串中的出現次數。

sizeof archive 模式 emp tomat .... truct print sca

/**
題目:hdu3065 病毒侵襲持續中
鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3065
題意:N(N <= 1000)個長度不大於50的模式串(保證所有的模式串都不相同),
一個長度不大於2000000的待匹配串,求模式串在待匹配串中的出現次數。

思路:ac自動機做發,val標記每一個病毒串編號,通過print函數統計每一個病毒出現的次數。

AC自動機好文章:http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html
*/


#include<bits/stdc++.h>
using namespace
std; #define P pair<int,int> #define ms(x,y) memset(x,y,sizeof x) #define LL long long const int maxn = 22; const int mod = 1e9+7; const int maxnode = 50*1000+10; const int sigma_size = 26; int cnt[1005]; struct AhoCorasickAutomata { int ch[maxnode][sigma_size]; int val[maxnode]; int sz;
int f[maxnode]; int last[maxnode]; void clear(){sz = 1; memset(ch[0],0,sizeof ch[0]); } int idx(char c){return c-A; } void insert(char *s,int x) { int u = 0, n = strlen(s); for(int i = 0; i < n; i++){ int c = idx(s[i]); if(!ch[u][c]){ memset(ch[sz],
0, sizeof ch[sz]); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = x; } void find(char *T){ int n = strlen(T); int j = 0; for(int i = 0; i < n; i++){ if(T[i]>Z||T[i]<A){ j = 0; continue; } int c = idx(T[i]); //while(j&&!ch[j][c]) j = f[j]; j = ch[j][c]; if(val[j]) print(j); else if(last[j]) print(last[j]); } } void print(int j) { if(j){ cnt[val[j]]++; print(last[j]); } } void getFail(){ queue<int> q; f[0] = 0; for(int c = 0; c < sigma_size; c++){ int u = ch[0][c]; if(u){f[u] = 0; q.push(u); last[u] = 0;} } while(!q.empty()){ int r = q.front(); q.pop(); for(int c = 0; c < sigma_size; c++){ int u = ch[r][c]; if(!u){ ch[r][c] = ch[f[r]][c]; continue; }//if(!u) continue; q.push(u); int v = f[r]; while(v&&!ch[v][c]) v = f[v]; f[u] = ch[v][c]; last[u] = val[f[u]] ? f[u] : last[f[u]]; } } } } ac ; char s[2000005]; char t[1005][55]; int main() { int n, m; while(scanf("%d",&n)==1) { ac.clear(); ms(cnt,0); for(int i = 1; i <= n; i++){ scanf("%s",t[i]); ac.insert(t[i],i); } ac.getFail(); scanf("%s",s); ac.find(s); for(int i = 1; i <= n; i++){ if(cnt[i]){ printf("%s: %d\n",t[i],cnt[i]); } } } return 0; } /* 3 AA BB CC ooxxCC%dAAAoen....END */

hdu3065 病毒侵襲持續中 AC自動機入門題 N(N <= 1000)個長度不大於50的模式串(保證所有的模式串都不相同), 一個長度不大於2000000的待匹配串,求模式串在待匹配串中的出現次數。