18.12.30 sssxTrie图

Posted yalphait

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18.12.30 sssxTrie图相关的知识,希望对你有一定的参考价值。

Trie树(字典树)

树中任一结点p都对应于一个字符串S,S由从根出发走到p所经过的边上的字符构成

数据结构

struct trienode
{
    trienode * child[26] ;
    //假设所有字符就是26个小写字母
    trienode() {
        memset(child,0,
        sizeof(child));
    }
};

操作

插入串

 1 void build(string s, trienode * root)
 2 {
 3     trienode* p=root;
 4     for (int i=0;i<s.size();++i)
 5     {
 6         if (p->child[s[i]-’a’]== NULL)
 7             p->child[s[i] -’a’] = new trienode(); //初始化新的节点
 8         p=p->child[s[i] -’a’];
 9     }
10 }

(复杂度为模式串长度)

Trie图(AC自动机)

可以由Trie树为基础构造

终止节点:每个模式串最后一个结点

危险结点:终止节点和前缀指向危险结点的结点。

包含前缀指针(next),结点p(字符串为S)的前缀指针指向的结点q的字符串为T满足:T是其他串中最长的S的一个后缀且不可等于S(可以为空串,即root)

求母串包含哪些模式串,将母串输入在Trie图上行走走到终止节点就表示匹配了相应的模式串

数据结构

int nNodesCount=0;
struct CNode
{
    CNode * pChilds[LETTERS];
    CNode * pPrev; //前缀指针
    bool bBadNode; //是否是危险节点
    CNode() {
        memset(pChilds,0,sizeof(pChilds));
        bBadNode = false;
        pPrev = NULL;
    }
}Tree[MAXN];

操作

在Trie树上添加前缀指针

  • 用BFS按深度由浅到深求每一个结点的前缀指针
  • 对于结点P,设其父节点与其连边上的字符为ch,找到父节点的前缀指针指向的结点看它与儿子的边有没有一条是ch的,如果有就把这个儿子作为P的前缀指针指向,没有继续用这个结点的前缀指针向上找。
 1 void BuildDfa( ) { //在trie树上加前缀指针
 2     for( int i = 0;i < LETTERS ;i ++ )
 3         Tree[0].pChilds[i] = Tree + 1;
 4         Tree[0].pPrev = NULL;
 5         Tree[1].pPrev = Tree;
 6         deque<CNode * > q;
 7         q.push_back(Tree+1);
 8         while( ! q.empty() ){
 9             CNode * pRoot = q.front();
10             q.pop_front();
11             for( int i = 0; i < LETTERS ; i ++ ) {
12                 CNode * p = pRoot->pChilds[i];
13                 if( p) {
14                     CNode * pPrev = pRoot->pPrev;
15                     while( pPrev->pChilds[i] == NULL)
16                         pPrev = pPrev->pPrev;
17                     p->pPrev = pPrev->pChilds[i];
18                     if( p->pPrev-> bBadNode)
19                         p-> bBadNode = true;
20                     //前缀指针指向的节点是危险节点,则自己也是危险节点
21                     q.push_back(p);
22                 }
23             }
24         } //对应于while( ! q.empty() )
25 }

母串匹配

  • 从root和母串第一个字符出发
  • 若当前点P不存在通过当前字符连接的儿子,则考察P的前缀指针指向的结点Q,依次类推直到找到。母串指针指向下一个字符继续遍历。
  • 如果遍历过程中经过了某个终止结点,说明S包含该终止结点代表的模式串。
  • 若遍历过程中经过了某个非终止结点的危险结点则可以顺着前缀指针找到一个终止结点,这个终止结点代表的串被S包含。
  • 复杂度:S的长度
 1 bool SearchDfa(char * s)
 2 {//返回值为true则说明包含模式串
 3     CNode * p = Tree + 1;
 4     for( int i = 0; s[i] ; ++i) {
 5         while( p->pChilds[s[i]-a] == NULL)
 6             p = p->pPrev;
 7         p = p->pChilds[s[i]-a];
 8         if( p-> bBadNode)
 9             return true;
10     }
11     return false;
12 }

以上是关于18.12.30 sssxTrie图的主要内容,如果未能解决你的问题,请参考以下文章

如何将 r ggplot 图存储为 html 代码片段

18.12.30 sssx线段树

炫酷 CSS 背景效果的 10 个代码片段

EasyClick 运行代码片段出Null

EasyClick 运行代码片段出Null

轻松保存重复多用的代码片段