解题思路:
对AC自动机算法的理解和应用,要注意的是,题目中的字符是128个ASCII码,而不是常用的26个英文字符,因此子节点的数目为128.
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <vector> #include <queue> #include <string.h> #include <stack> #include <algorithm> using namespace std; struct Trie { int next[210*500][128],fail[210*500],end[210*500]; int root,L; int newnode() { for(int i = 0;i < 128;i++) next[L][i] = -1; end[L++] = -1; return L-1; } void init() { L = 0; root = newnode(); } void insert(char buf[], int id) { int len = strlen(buf); int now = root; for(int i = 0;i < len;i++) { if(next[now][buf[i]] == -1) next[now][buf[i]] = newnode(); now = next[now][buf[i]]; } end[now] = id; } void build() { queue<int>Q; fail[root] = root; for(int i = 0;i < 128;i++) if(next[root][i] == -1) next[root][i] = root; else { fail[next[root][i]] = root; Q.push(next[root][i]); } while( !Q.empty() ) { int now = Q.front(); Q.pop(); for(int i = 0;i < 128;i++) if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } int vis[510]; int query(char buf[],int n, int id) { int len = strlen(buf); int now = root; int flag = 0; memset(vis, 0, sizeof(vis)); for(int i = 0;i < len;i++) { now = next[now][buf[i]]; int temp = now; while( temp != root ) { if(end[temp] != -1) { vis[end[temp]] = 1; flag = 1; } temp = fail[temp]; } } if(!flag) return 0; printf("web %d:", id); for(int i=1;i<=n;i++) if(vis[i]) printf(" %d", i); printf("\n"); return 1; } }; char buf[10010]; Trie ac; int main() { int n, m; while(scanf("%d", &n)!=EOF) { ac.init(); for(int i=1;i<=n;i++) { scanf("%s", buf); ac.insert(buf, i); } ac.build(); int ans = 0; scanf("%d", &m); for(int i=1;i<=m;i++) { scanf("%s", buf); if(ac.query(buf, n, i)) ans++; } printf("total: %d\n", ans); } return 0; }
时间: 2024-12-14 15:02:25