// hdu 2896 AC自动机 // // 题目大意: // // 给你n个短串,然后给你q串长字符串,要求每个长字符串中 // 是否出现短串,出现的短串各是什么 // // 解题思路: // // AC自动机,插入单词,构建自动机,然后查询就可以了。 // // 感悟: // // 哎,自己AC自动机果然刚学,还只会个模板,自动机构没构建 // 都不知道。。。继续加油吧~~~FIGHTING! #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; const int MAX_NODE = 200000; const int SIGMA_SIZE = 131; struct Aho_Corasick{ int ch[MAX_NODE][SIGMA_SIZE]; int val[MAX_NODE]; int cnt[508]; int sz; int last[MAX_NODE]; int f[MAX_NODE]; void clear(){ memset(cnt,0,sizeof(cnt)); } void init(){ sz = 1; memset(ch[0],0,sizeof(ch[0])); val[0] = 0; } int idx(char c){ return c - ‘a‘; } void insert(char *s,int v){ int u = 0; int n = strlen(s); for (int i=0;i<n;i++){ //int c = idx(s[i]); int c = 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] = v; } void getfail(){ queue<int> que; for (int c = 0; c < SIGMA_SIZE ; c++){ int u = ch[0][c]; if (u){ que.push(u); last[u] = 0; f[u] = 0; } } while(!que.empty()){ int r = que.front(); que.pop(); for (int c = 0; c < SIGMA_SIZE ; c++){ int u = ch[r][c]; if (!u) continue; que.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]]; } } } void get_cnt(int u){ if (u){ cnt[val[u]]++; get_cnt(last[u]); } } void query(char *s){ int u = 0; int n = strlen(s); for (int i=0;i<n;i++){ //char c = idx(s[i]); char c = s[i]; while( u && !ch[u][c]) u = f[u]; u = ch[u][c]; if (val[u]){ get_cnt(u); } else if (last[u]){ get_cnt(last[u]); } } } }ac; char str[10009]; int n; void print(int x,int &num){ int flag = 0; for (int i=1;i<=n;i++){ if (ac.cnt[i]){ flag = 1; break; } } if (!flag) return; printf("web %d:",x); for (int i=1;i<=n;i++){ if (ac.cnt[i]){ printf(" %d",i); } } puts(""); num++; } void input(){ ac.init(); for (int i=1;i<=n;i++){ scanf("%s",str); ac.insert(str,i); } int q; int num = 0; ac.getfail(); scanf("%d",&q); int x = 1; for (int i=1;i<=q;i++){ scanf("%s",str); ac.clear(); ac.query(str); print(i,num); } printf("total: %d\n",num); } int main(){ //freopen("1.txt","r",stdin); while(scanf("%d",&n)!=EOF){ input(); } }
时间: 2024-10-17 10:43:47