UVa Live 4670 Dominating Patterns - Aho-Corasick自动机

Posted 阿波罗2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa Live 4670 Dominating Patterns - Aho-Corasick自动机相关的知识,希望对你有一定的参考价值。

题目传送门

  快速的通道I

  快速的通道II

题目大意

  给定一堆短串,和一个文本串,问哪些短串在文本串中出现的次数最多。

  我觉得刘汝佳的做法,时间复杂度有问题。只是似乎这道题短串串长太短不好卡。比如给出的串是一坨$a$。暴力跳$last$会比较gg。

  考虑如何计算一个短串在长串中的出现次数。

  当短串在长串的某个位置出现的时候,这意味着它的结束位置在fail树上的祖先中某个状态是短串的终止状态。

  我们会在长串经过的每个状态都去做这样一个操作来统计每个短串出现的次数。

  这个可以看成在fail树上的以根为端点的链上修改操作。

  由于询问可以看成是离线的,所以每次可以单点修改cnt,最后做一次前缀和。

Code

  1 /**
  2  * UVa Live
  3  * Problem#4670
  4  * Accepted
  5  * Time: 45ms
  6  */
  7 #include <iostream>
  8 #include <cstring>
  9 #include <cstdio>
 10 #include <queue>
 11 using namespace std;
 12 typedef bool boolean;
 13 
 14 const int MaxNode = 10505, N = 152, L = 75;
 15 
 16 typedef class TrieNode {
 17     public:
 18         int cnt;
 19         TrieNode* ch[26];
 20         TrieNode* fail;
 21 }TrieNode;
 22 
 23 TrieNode pool[MaxNode];
 24 TrieNode *top;
 25 
 26 TrieNode* newnode() {
 27     top->cnt = 0;
 28     memset(top->ch, 0, sizeof(top->ch));
 29     top->fail = NULL;
 30     return top++;
 31 }
 32 
 33 typedef class AhoCorasick {
 34     public:
 35         TrieNode* rt;
 36 
 37         AhoCorasick() {
 38             top = pool;
 39             rt = newnode();
 40         }
 41 
 42         TrieNode* insert(char* str) {
 43             TrieNode* p = rt;
 44             for (int i = 0, c; str[i]; i++) {
 45                 c = str[i] - a;
 46                 if (!p->ch[c])
 47                     p->ch[c] = newnode();
 48                 p = p->ch[c];
 49             }
 50             return p;
 51         }
 52 
 53         void build() {
 54             queue<TrieNode*> que;
 55             rt->fail = NULL;
 56             que.push(rt);
 57             while (!que.empty()) {
 58                 TrieNode* p = que.front();
 59                 que.pop();
 60                 for (int i = 0; i < 26; i++) {
 61                     TrieNode *np = p->ch[i];
 62                     if (!np)    continue;
 63                     que.push(np);
 64                     TrieNode* f = p->fail;
 65                     while (f && !f->ch[i])    f = f->fail;
 66                     if (!f)
 67                         np->fail = rt;
 68                     else
 69                         np->fail = f->ch[i];
 70                 }
 71             }
 72         }
 73 
 74         void query(char *str) {
 75             TrieNode *p = rt;
 76             for (int i = 0; str[i]; i++) {
 77                 int c = str[i] - a;
 78                 while (p && !p->ch[c])    p = p->fail;
 79                 if (!p)
 80                     p = rt;
 81                 else
 82                     p = p->ch[c];
 83                 p->cnt++;    
 84             }
 85             for (p = top - 1; p != pool; p--)
 86                 p->fail->cnt += p->cnt;
 87         }
 88 }AhoCorasick;
 89 
 90 int n;
 91 AhoCorasick ac;
 92 char S[1000005];
 93 char T[N][L];
 94 TrieNode* ps[N];
 95 
 96 inline boolean init() {
 97     scanf("%d", &n);
 98     if (!n)    return false;
 99     ac = AhoCorasick();
100     for (int i = 1; i <= n; i++) {
101         scanf("%s", T[i]);
102         ps[i] = ac.insert(T[i]);
103     }
104     scanf("%s", S);
105     return true;
106 }
107 
108 inline void solve() {
109     ac.build();
110     ac.query(S);
111     int maxt = 0;
112     for (int i = 1; i <= n; i++)
113         if (ps[i]->cnt > maxt)
114             maxt = ps[i]->cnt;
115     printf("%d\n", maxt);
116     for (int i = 1; i <= n; i++)
117         if (ps[i]->cnt == maxt)
118             puts(T[i]);
119 }
120 
121 int main() {
122     while(init())
123         solve();
124     return 0;
125 }

以上是关于UVa Live 4670 Dominating Patterns - Aho-Corasick自动机的主要内容,如果未能解决你的问题,请参考以下文章

UVALive 4670 Dominating Patterns

LA 4670 Dominating Patterns (AC自动机)

UVALive-4670 Dominating Patterns / 洛谷 3796 模板AC自动机

LA4670 Dominating Patterns AC自动机模板

LA 4670 Dominating Patterns (AC自动机)

LA_4670_Dominating_Patterns_(AC自动机+map)