字符串匹配——字典树(Trie树)、后缀树(suffix

更新时间:2023-06-16 05:48:05 阅读: 评论:0

字符串匹配——字典树(Trie树)、后缀树(suffix tree)
字典树(Trie树):
它的优点是:利⽤字符串的公共前缀来减少查询时间,最⼤限度地减少⽆谓的字符串⽐较,查询效率⽐哈希表⾼。
字典树的特点:根节点不包含字符,除根节点外每⼀个节点都只包含⼀个字符;从根节点到某⼀节点,路径上经过的字符连接起来,为该节点对应的字符串;每个节点的所有⼦节点包含的字符都不相同。
字典树的创建炖冬瓜的家常做法
1. 从根节点开始⼀次搜索
2. 取得要查找关键词的第⼀个字母,并根据该字母选择对应的⼦树并转到该⼦树继续进⾏检索
3. 在相应的⼦树上,取得要查找关键词的第⼆个字母,并进⼀步选择对应的⼦树进⾏检索
4. 迭代过程...
5. 在某个节点处,关键词的所有字母已被取出,则读取附在该节点上的信息,即完成查找
字典树的应⽤
1、字典树在串的快速检索中的应⽤
#define MAX 26 //字符集⼤⼩
typedef struct TrieNode {
int nCount;
struct TrieNode *next[MAX];  //每个节点⽤⼀个数组存储⼦节点
膻味
}TrieNode;
TrieNode Memory[1000000];
int allocp =0;
TrieNode *CreateTrieNode() {说反话游戏
int i;
TrieNode *p;
p = &Memory[allocp++];
p->nCount = 1;
for(i =0 ; i < MAX ; i++) {
p->next[i] = NULL;
}
return p;
}
void InrtTrie(TrieNode * &pRoot , char*s) { //插⼊ & 建树
int i, k;西服怎么叠
TrieNode *p;
if(!(p = pRoot)) {
p = pRoot = CreateTrieNode();
}
i = 0;
while(s[i]) {
k = s[i++] - 'a';
if(p->next[k])
p->next[k]->nCount++;
el
p->next[k] = CreateTrieNode();
p = p->next[k];
}
}
int SearchTrie(TrieNode * &pRoot , char*s) {  //查询单词的出现次数
TrieNode *p;
int i , k;
if(!(p = pRoot)) {
return 0;
}
i = 0;
while(s[i]) {深思熟虑什么意思
k = s[i++] -'a';
打坐的好处
if(p->next[k] == NULL) return 0;
p = p->next[k];
}
return p->nCount;
}
2. 字典树在“串”排序⽅⾯的应⽤
给定N个互不相同的仅由⼀个单词构成的英⽂名,让你将他们按字典序从⼩到⼤输出
⽤字典树进⾏排序,采⽤数组的⽅式创建字典树,这棵树的每个结点的所有⼉⼦很显然地按照其字母⼤⼩排序。对这棵树进⾏先序遍历即可
3. 字典树在最长公共前缀问题的应⽤
对所有串建⽴字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为最近公共祖先问题
后缀树
Ukkonen算法穿件后缀树www.oschina/translate/ukkonens-suffix-tree-algorithm-in-plain-english
字符串中没有重复字符的情况:
字符串abc。从左开始,第⼀次插⼊单个字符“a“创建⼀个从根节点到⼀个叶节点的边,和作为[0,#)的标签,这意味着边代表了⼦串在位置0开始,结束在当前的结尾。我使⽤符号#来表⽰当前末尾,这是在位置1(a之后的右边)。现在这棵树看起来如下:⽽其意义如下:
现在我们前进到位置2(b的右边)。我们每个步骤的⽬标是插⼊⾄当前位置的所有后缀。
我们通过以下动作完成⽬标:
扩展已存在边a为ab
插⼊⼀条新边b
在我们的图⽰⾥,它看起来如下:
⽽其意义如下:
接着我们再次增加位置,并且修改树:给每个已经存在的边增加c,插⼊⼀条表⽰新后缀c的边。
梦见很多在我们的图⽰⾥,它看起来如下:肥肥的瓜
⽽其意义如下:
字符串中有简单的重复:
字符串abcabxabcd。
我们为每条边引⼊另外两个变量:
活动点,它是⼀个三元组(活动节点,活动边,活动长度)
剩余后缀数,它是⼀个整数,来说明我们需要插⼊多少个新的后缀。
在简单的abc例⼦⾥,活动点总是(root,'0x',0),也就是说,活动节点是根节点,活动边是由空字符'0x'指定的边,活动长度是0;在每个步骤开始时剩余后缀数总是设置为1,它的意义是我们主动插⼊到每⼀步骤末尾的后缀数⽬是1(总是最后⼀个字符)。
当我们给根节点插⼊当前最后⼀个字符a的时候,我们特别注意到已经存在⼀条以a开始的边。当发现我们需要插⼊的最终后缀已经存在在这棵树⾥的时候,这棵树本⾝根本就没有改变,我们只是修改了活动节点和剩余后缀数。我们我们修改活动点为(root,'a',1),表⽰这棵树就不再是能准确的表⽰⾄当前位置的后缀树了,不过它包含了所有的后缀(因为最终的后缀a隐含地包含了)。我们还增加了剩余后缀数,那么在下⼀步骤开始的时候,剩余后缀数为2。
我们修改当前的位置#为5。这将⾃动地如下更新这棵树:
⽽且由于剩余后缀数为2 ,我们需要插⼊⽬前位置的两个最终后缀:ab和b。

本文发布于:2023-06-16 05:48:05,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1040669.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:节点   后缀   活动   剩余   查询   字符串
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图