P3796 【模板】AC自动机(加强版)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e6+5; 4 struct word { 5 string str; 6 int num; // 出现次数 7 int pos; // 出现位置 8 }words[maxn]; 9 bool cmp(word x, word y) { 10 if (x.num == y.num) return x.pos < y.pos; 11 return x.num > y.num; 12 } 13 struct Aho_Corasock_Automaton { 14 struct node { 15 int fail; // 失配指针 16 int son[26]; // 子节点的位置 17 int end; // 标记以该节点结尾的模式串的编号 18 }Trie[maxn]; 19 int cnt = 0; // Trie指针 20 void clear(int x) { // 清空节点信息 21 memset(Trie[x].son,0,sizeof(Trie[x].son)); 22 Trie[x].fail = Trie[x].end = 0; 23 } 24 void insert(char *s, int num) { 25 int len = strlen(s); 26 int now = 0; // Trie当前指针 27 for (int i = 0; i < len; ++i) { 28 if (Trie[now].son[s[i]-'a'] == 0) { // 如果没有这个子节点 29 Trie[now].son[s[i]-'a'] = ++cnt; // 构造该节点 30 clear(cnt); // 清空新构造的节点里面的信息 31 } 32 now = Trie[now].son[s[i]-'a']; 33 } 34 Trie[now].end = num; // 标记以该节点结尾是哪个模式串 35 } 36 void get_fail() { // 构造fail指针 37 queue<int> que; 38 for (int i = 0; i < 26; ++i) { // 先提前构造第二层 39 if (Trie[0].son[i] != 0) { // 如果存在该节点 40 Trie[Trie[0].son[i]].fail = 0; // fail指向root节点 41 que.push(Trie[0].son[i]); // 加入队列 42 } 43 } 44 while (!que.empty()) { // bfs求fail指针 45 int u = que.front(); que.pop(); 46 for (int i = 0; i < 26; ++i) { 47 if (Trie[u].son[i] != 0) { // 如果存在该子节点 48 // 子节点的fail指针指向当前节点的fail指针指向内容相同的子节点 49 Trie[Trie[u].son[i]].fail = Trie[Trie[u].fail].son[i]; 50 que.push(Trie[u].son[i]); // 加入队列 51 } 52 else { // 如果不存在这个子节点 53 // 当前节点的该子节点指向当前节点的fail指针指向的止隔子节点 54 Trie[u].son[i] = Trie[Trie[u].fail].son[i]; 55 } 56 } 57 } 58 } 59 void query(char *s) { 60 int len = strlen(s); 61 int now = 0, ans = 0; // 当前Trie指针,答案ans 62 for (int i = 0; i < len; ++i) { 63 now = Trie[now].son[s[i]-'a']; 64 for (int t = now; t != 0; t = Trie[t].fail) { // 暴力搜索 65 words[Trie[t].end].num++; // 以该节点为结尾的模式串次数加一 66 } 67 } 68 } 69 }AC; 70 char t[maxn], s[maxn]; 71 int main() { 72 int n; 73 while (scanf("%d",&n) != EOF && n) { 74 AC.cnt = 0, AC.clear(0); 75 for (int i = 1; i <= n; ++i) { 76 cin >> words[i].str; 77 strcpy(t,words[i].str.c_str()); 78 words[i].pos = i; 79 words[i].num = 0; 80 AC.insert(t,i); 81 } 82 AC.Trie[0].fail = 0; 83 AC.get_fail(); 84 scanf("%s",s); 85 AC.query(s); 86 sort(words+1,words+1+n,cmp); 87 printf("%d\n%s\n",words[1].num,words[1].str.c_str()); 88 for (int i = 2; i <= n; ++i) { 89 if (words[i].num == words[1].num) { 90 printf("%s\n",words[i].str.c_str()); 91 } 92 else break; 93 } 94 } 95 return 0; 96 }

浙公网安备 33010602011771号