zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    .net UserControl用户控件传值
    (DevExpress2011控件教程)ASPXTreeList 范例2: ASPxTreeList杂项设置
    [转 逆水行船]Oracle中创建表,创建序列,创建自增字段,添加注释, 添加记录,添加触发器,提交
    封装基本类在项目中的应用
    [原创]visual 2008下使用Enterprise library4.01连接Oracle的例子
    [转thyking xiao's blog]asp.net 2.0实现多语言(一)
    jquery autocomplete 实现搜索提示功能,中文/拼音也没问题
    jQuery API$.extend(target,prop1,propN)
    通用权限管理设计 之 数据库结构设计
    jQuery弹出层插件Dialog
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4592595.html
Copyright © 2011-2022 走看看