标签:16px 字母 字符连接 字典 int desc trie图 front 插入
树中任一结点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树为基础构造
终止节点:每个模式串最后一个结点
危险结点:终止节点和前缀指向危险结点的结点。
包含前缀指针(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树上添加前缀指针
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 }
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 }
标签:16px 字母 字符连接 字典 int desc trie图 front 插入
原文地址:https://www.cnblogs.com/yalphait/p/10199820.html