Trie图

AC自动机是KMP的多串形式,当文本串失配时,AC自动机的fail指针告诉我们应该跳到哪里去继续匹配(跳到当前匹配串的最长后缀去),所以AC自动机的状态是有限的

但是AC自动机具有不确定性, 比如要求x结点的孩子c的fail指针(x->next[c]->fail), 如果x的fail指针指向的结点没有c孩子(x-fail->next[c]==NULL),

那么就要去看x的fail指针指向的结点的的fail指针指向的结点有没有孩子c(x->fail->fail->next[c] 是否为NULL),一直这样子迭代, 知道fail指针指向根结点为止

 

这样子的原因在于next指针的指向可能为空, Trie图就是补全了这些next指针的AC自动机,所以Trie图是确定性的有限状态自动机

那么如果补全这些next指针呢?

首先让第二层为空的next指针(第一层是根结点)都指向root,这是成里的, 如果匹配的时候如果第一个字符就不匹配, 那么肯定是回到root重新匹配

然后让下一层为空的next[i]指针指向上一层fail指针指向的next[i]指针(即也是指向自己的最长后缀)

Trie图的fail指针的求法与AC自动机一样, 这样子就能构件出Trie图了

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 #pragma warning(disable:4996)
15 typedef unsigned __int64 LL;                   
16 const int INF = 1<<30;
17 /*
18 */
19 const int N = 40;
20 struct Node
21 {
22     int fail, next[26];
23     bool isWord;
24     void init()
25     {
26         fail = -1;
27         isWord = false;
28         for (int i = 0; i < 26; ++i)
29             next[i] = -1;
30     }
31 }Trie[N];
32 int size;
33 void insert(int root, char *str)
34 {
35     int idx, cur = root;
36     for (int i = 0; str[i]; ++i)
37     {
38         idx = str[i] - 'a';
39         if (Trie[cur].next[idx] == -1)
40         {
41             Trie[size].init();
42             Trie[cur].next[idx] = size++;
43         }
44         cur = Trie[cur].next[idx];
45     }
46     Trie[cur].isWord = true;
47 }
48 void makeFail(int root)
49 {
50     queue<int> q;
51     for (int i = 0; i < 26; ++i)
52     {
53         if (Trie[root].next[i] == -1)
54             Trie[root].next[i] = root;
55         else
56         {
57             Trie[Trie[root].next[i]].fail = root;
58             q.push(Trie[root].next[i]);
59         }
60     }
61     while (!q.empty())
62     {
63         int cur = q.front();
64         q.pop();
65         for (int i = 0; i < 26; ++i)
66         {
67             if (Trie[Trie[cur].fail].isWord)
68                 Trie[cur].isWord = true;
69             if (Trie[cur].next[i] == -1)
70                 Trie[cur].next[i] = Trie[Trie[cur].fail].next[i];
71             else
72             {
73                 Trie[Trie[cur].next[i]].fail = Trie[Trie[cur].fail].next[i];
74                 q.push(Trie[cur].next[i]);
75             }
76         }
77     }
78 }
79 
80 int main()
81 {
82     int n, L;
83     char word[10];
84     while (scanf("%d", &n,) != EOF)
85     {
86         Trie[0].init();
87         Trie[0].fail = 0;
88         size = 1;
89         for (int i = 0; i < n; ++i)
90         {
91             scanf("%s", word);
92             insert(0, word);
93         }
94         makeFail(0);
95     
96         
97     }
98     return 0;
99 }

 

posted @ 2015-06-21 22:45  justPassBy  阅读(199)  评论(0编辑  收藏  举报