Suffix树,后缀树
body, table{font-family: 微软雅黑; font-size: 13.5pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}
eg: BIBS. 构造的后缀树如右图所示: 对于每个结点,包含两个数据成员,该结点出发可以到达的其他结点的指针(map)、从根结点到子孙结点的路径构成的子串在源字符串中的开始位置(vector)。 map<char,结点指针>、vector<int> 右图中包含4个子串,BIBS,BS,IBS,S。 BIBS中vector有两个数据0和2,因为BIBS和BS在源字符串中的位置是0和2.char==B,map有两个数据成员,一个为I和指向I的指针,另一个为S和指向S的指针。 |
|
#include<iostream>
#include<vector>
#include<map>
#include<string>
using namespace std;
class SuffixTreeNode //后缀树的结点类
{
public:
SuffixTreeNode() { }
void insertString(string s,int idx); //往后缀树中插入一个字符串
vector<int> getIndex(string s); //获取字符串在源字符串中出现的位置
~SuffixTreeNode();
private:
map<char,SuffixTreeNode*> subTreeNode; //结点出发可以到达的下一个字符以及指向该结点的指针
vector<int> index; //存放子字符串在S中的起始位置
//可能有多个子串,或者从一个结点出发可以找到多个不同子串
};
void SuffixTreeNode::insertString(string s,int idx)
{//建立后缀树
index.push_back(idx); //字符串的起始位置保存.放到这里的原因,从root结点开始,等到字后一个字符的时候Str已被耗尽,也就是map没有元素了,但是这个结点index却要保存
if(s.length()>0) //如果字符串还没有耗尽,递归接着向下构造后缀树
{
char value = s[0]; //结点value的值解释字符串的第一个字符
//判断该字符在不在该结点的map中,在就继续向下插入下一个字符,不在就新建一个结点并在当前结点的map中保存相关信息
SuffixTreeNode* next = NULL;
if(subTreeNode.find(value)!=subTreeNode.end()) //如果结点中存在该字符,next指针指向该结点
{
next = subTreeNode.find(value)->second;
}
else //没有该字符,就新建一个结点,并在当前结点的map中保存这个字符值,以及到这个字符的指针
{
SuffixTreeNode* node = new SuffixTreeNode;
subTreeNode.insert(::make_pair(value,node));
next = node;
}
//递归利用字符串中的下一个字符接着构造后缀树
string subStr = s.substr(1);
next->insertString(subStr,idx); //这个子串的起始位置是idx,以后一直是这个,不会变
}
}
vector<int> SuffixTreeNode::getIndex(string s)
{
//挨个字符匹配,最后返回最后一个字符所指向的结点的vector
if(""==s) //成功匹配到最后返回该结点的index
return index;
else
{
if(subTreeNode.find(s[0])!=subTreeNode.end())
return ((subTreeNode.find(s[0]))->second)->getIndex(s.substr(1)); //接着向下匹配
else
{//找不到,直接返回空
return vector<int>(0);
}
}
}
SuffixTreeNode::~SuffixTreeNode()
{//挨个释放动态申请的结点内存
for(auto it = subTreeNode.begin();it!=subTreeNode.end();++it)
{
delete it->second; //这里是一个递归过程
it->second = NULL;
}
}
|
class SuffixTree
{
public:
SuffixTree(string str); //用字符串(源串)初始化一个后缀树
vector<int> getIndex(string str); //获取一个字符串在源串中出现的位置
~SuffixTree();
private:
SuffixTreeNode* _root;
};
SuffixTree::SuffixTree(string str)
{
_root = new SuffixTreeNode();
for(int idx=0;idx!=str.length();++idx)
{
string subStr = str.substr(idx);
_root->insertString(subStr,idx);
}
}
vector<int> SuffixTree::getIndex(string str)
{
return _root->getIndex(str);
}
SuffixTree::~SuffixTree()
{
delete _root;
_root = NULL;
}
int main(int argc,char** argv)
{
string testString = "mississippi";
string arr[4] = {"is","sip","hi","sis"};
SuffixTree tree(testString);
for(int idx=0;idx!=4;++idx)
{
vector<int> ans = tree.getIndex(arr[idx]);
cout<<arr[idx]<<" ";
if(0!=ans.size())
{
for(int iidx=0;iidx!=ans.size();++iidx)
{
cout<<ans[iidx]<<" ";
}
cout<<endl;
}
else
{
cout<<"not find!"<<endl;
}
}
system("pause");
}
|
Suffix树,后缀树的更多相关文章
- 字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组
涉及到字符串的问题,无外乎这样一些算法和数据结构:自动机 KMP算法 Extend-KMP 后缀树 后缀数组 trie树 trie图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...
- 【Todo】字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树
另开一文分析字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树. 先来一个汇总, 算法: 本文中提到的字符串匹配算法有:KMP, BM, Horspool, Sunday, BF, ...
- BZOJ 3879: SvT [虚树 后缀树]
传送门 题意: 多次询问,给出一些后缀,求两两之间$LCP$之和 哈哈哈哈哈哈哈竟然$1A$了,刚才还在想如果写不好这道题下节数学就不上了,看来是上天让我上数学课啊 $Suffix\ Virtual\ ...
- 后缀树(suffix tree)
参考: 从前缀树谈到后缀树 后缀树 Suffix Tree-后缀树 字典树(trie树).后缀树 一.前缀树 简述:又名单词查找树,tries树,一种多路树形结构,常用来操作字符串(但不限于字符串), ...
- [算法]从Trie树(字典树)谈到后缀树
我是好文章的搬运工,原文来自博客园,博主July_,地址:http://www.cnblogs.com/v-July-v/archive/2011/10/22/2316412.html 从Trie树( ...
- 012-数据结构-树形结构-哈希树[hashtree]、字典树[trietree]、后缀树
一.哈希树概述 1.1..其他树背景 二叉排序树,平衡二叉树,红黑树等二叉排序树.在大数据量时树高很深,我们不断向下找寻值时会比较很多次.二叉排序树自身是有顺序结构的,每个结点除最小结点和最大结点外都 ...
- Trie树(代码),后缀树(代码)
Trie树系列 Trie字典树 压缩的Trie 后缀树Suffix tree 后缀树--ukkonen算法 Trie是通过对字符串进行预先处理,达到加快搜索速度的算法.即把文本中的字符串转换为树结构, ...
- 后缀树的建立-Ukkonen算法
参考: Ukkonen算法讲解 Ukkonen算法动画 Ukkonen算法,以字符串abcabxabcd为例,先介绍一下运算过程,最后讨论一些我自己的理解. 需要维护以下三个变量: 当前扫描位置# 三 ...
- [模板] 后缀自动机&&后缀树
后缀自动机 后缀自动机是一种确定性有限状态自动机, 它可以接收字符串\(s\)的所有后缀. 构造, 性质 翻译自毛子俄罗斯神仙的博客, 讲的很好 后缀自动机详解 - DZYO的博客 - CSDN博客 ...
- POJ2774 --后缀树解法
POJ2774 Long Long Message --后缀树解法 原题链接 题意明确说明求两字符串的最长连续公共子串,可用字符串hash或者后缀数据结构来做 关于后缀树 后缀树的原理较为简单,但 \ ...
随机推荐
- python读写json文件(转)
https://www.cnblogs.com/bigberg/p/6430095.html 利用python中的json库处理数据(包含json的四种方法:dumps.dump.loads.load ...
- G.711是一种由国际电信联盟(ITU-T)制定的音频编码方式
http://zh.wikipedia.org/zh-cn/G.711 ITU-T G.711 page ITU-T G.191 software tools for speech and audio ...
- 20170821xlVBA隐藏空行
Sub HideBlankRowsBetweenUsedRange() Dim URows As Range, i As Long, EndRow As Long With ActiveSheet E ...
- Hadoop – The Definitive Guide Examples,,IntelliJ
IntelliJ Project for Building Hadoop – The Definitive Guide Examples http://vichargrave.com/intellij ...
- Android--------内存泄露工具LeakCanary
什么是内存泄露 一些对象有着有限的生命周期.当这些对象所要做的事情完成了,我们希望他们会被回收掉.但是如果有一系列对这个对象的引用,那么在我们期待这个对象生命周期结束的时候被收回的时候,它是不会被回收 ...
- 02 flask 请求钩子、异常捕获、上下文、Flask-Script 扩展、jinja2 模板引擎、csrf防范
一 请求勾子 在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如: 在请求开始时,建立数据库连接: 在请求开始时,根据需求进行权限校验: 在请求结束时,指定数据的交互格式: 为了让每个 ...
- linux中用composer安装yii框架
我的服务器是安装的是lanmp环境 如果环境版本比较低的话,建议升级一下版本 升级版本命令:./lanmp.sh cus 全都选择最高的.完成之后: curl -sS https://getcompo ...
- python and or的理解规则
>>> 'a' and 'b' 'b' >>> '' and 'b' '' >>> 'a' and 'b' and 'c' 'c’ 解释:在布尔上 ...
- Music in Car CodeForces - 746F (贪心,模拟)
大意: n首歌, 第$i$首歌时间$t_i$, 播放完获得贡献$a_i$, 最多播放k分钟, 可以任选一首歌开始按顺序播放, 最多选w首歌半曲播放(花费时间上取整), 求贡献最大值. 挺简单的一个题, ...
- URL与URI的含义及区别
1.1 什么是URI? 简单点说:URI就是通用资源标志符,不理解是吧,我第一次听说也是不理解. 进一步说:网络上的一些资源(文档.图片.音频.视频.程序等)都是有一些通用资源标识(Universal ...