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

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号