AC自动机模版

来源:互联网 发布:大数据对银行业的影响 编辑:程序博客网 时间:2024/05/16 13:52
Trie树上的前缀指针:假设有一个节点k,他的前缀指针指向j。那么k,j满足这个性质:设root到j的距离为n,则从k之上的第n个节点到k所组成的长度为n的单词,与从root到j所组成的单词相同。
如何构建前缀指针:根据KMP的启发
root及其儿子的前缀指针指向root
对于每个节点:设这个节点上的字母为C,沿着他父亲的前缀指针遍历,直到访问到一个节点,他的儿子中也有字母为C的节点。然后把当前节点的前缀指针指向那个字母也为C的儿子。如果一直走到了root都没找到,那就把前缀指针指向root(可以看做遍历了多个Trie的next数组)
对于Tire树的每个结点,我们都要求生成其前缀指针
顺序问题:在生成一个结点的前缀指针,需要其父亲的前缀指针,以及这个指针指向的结点的前缀指针等等。这些前缀指针所在结点的深度都不可能比当前结点深,所以生成前缀指针采用BFS遍历字典树
#include <cstdio>#include <iostream>#include <cstring>#include <queue>using namespace std;#define maxn 11000char a[101], b[101];int t, n, ans;struct Tnode{       Tnode *next[26], *fail;       int cnt;       Tnode()       {              cnt = 0;              for (int i = 0;i < 26;i++)                  next[i] = NULL;              fail = NULL;       }}*root;void insert(char *s)//构建字典树;{     Tnode *p = root;     int i, len = strlen(s);     for (i = 0;i < len;i++)     {         if (p->next[s[i] - 'a'] == NULL)            p->next[s[i] - 'a'] = new Tnode();         p = p->next[s[i] - 'a'];     }     p->cnt = p->cnt + 1;//个数;}void build()//构建失败指针,利用bfs;{     int i, j;     root->fail = root;     queue<Tnode*> Q;//     queue<Tnode*>Q;     for (i = 0;i < 26;i++)     {         if (root->next[i] != NULL)         {                           root->next[i]->fail = root;                           Q.push(root->next[i]);//queue[rear++] = root->next[i];         }     }     while (!Q.empty())     {           Tnode *p = Q.front();           Q.pop();           for (i = 0;i < 26;i++)           {               if (p->next[i] == NULL) continue;               Q.push(p->next[i]);               Tnode *q = p->fail;               while (q->next[i] == NULL && q != root)                     q = q->fail;               if (q->next[i] != NULL)                  p->next[i]->fail = q->next[i];               else p->next[i]->fail = root;           }     }     return;}void query(char *s){     int len = strlen(s), i;     Tnode *p = root;     for (i = 0;i < len;i++)     {         while (p->next[s[i] - 'a'] == NULL && p != root)               p = p->fail;         if (p->next[s[i] - 'a'] != NULL) p = p->next[s[i] - 'a'];         Tnode *q = p;         while (q != root)         {               ans += q->cnt;               q->cnt = 0;//以免重复计算;               q = q->fail;         }     }     return;}int main(){    int i, j;    scanf ("%d", &t);    while (t--)    {          ans = 0;          root = new Tnode();          scanf ("%d", &n);          getchar();          for  (i = 0;i < n;i++)          {                gets(a);                insert(a);          }          build();          gets(b);          query(b);          printf ("%d\n", ans);    }    return 0;}


1 0
原创粉丝点击