第一次遇到后缀树这种数据结构,所以就去理解了一下,感觉原理不难懂,但是相比于前缀树,后缀树的代码实现还是有点麻烦。
后缀树常用于在母串s中查询子串p是否存在,并查询子串在母串中开始的位置
它的思路就是对于每个后缀树结点,都有一个map和vector
给一个例子:
//后缀树的实现
class SuffixTreeNode
{
private:
map<char, SuffixTreeNode*>children;//记录当前结点的子结点信息
vector<int>indexes;//记录子串在父串中的起始位置
public:
void insertString(string s, int index)//递归插入一个后缀子串
{
this->indexes.push_back(index);
if (s.size() == 0)return;
SuffixTreeNode*child = NULL;
if (this->children.find(s[0]) != this->children.end())//如果子串的首字符结点已经存在,那么就去map里找
{
child = this->children[s[0]];
}
else//否则,创建新的子结点,并存入map
{
child = new SuffixTreeNode();
this->children[s[0]] = child;
}
child->insertString(s.substr(1), index);//递归插入
}
vector<int>getIndexes(string s)
{
if (s.size() == 0)
return this->indexes;
if (this->children.find(s[0]) != this->children.end())
{
return children[s[0]]->getIndexes(s.substr(1));//递归查询
}
else
{
return{};
}
}
~SuffixTreeNode()
{
for (map<char, SuffixTreeNode*>::iterator iter = children.begin(); iter != children.end(); iter++)
{
delete iter->second;
}
}
};
class SuffixTree
{
private:
SuffixTreeNode*root;
public:
SuffixTree(string s)
{
root=new SuffixTreeNode();
for (int i = 0; i < s.size(); i++)
{
root->insertString(s.substr(i),i);//核心
}
}
vector<int>getIndexes(string s)
{
return root->getIndexes(s);
}
~SuffixTree()
{
if(root!=NULL)
delete root;
}
};
int main()
{
string testString = "BIBS";
SuffixTree mytree(testString);
vector<int>v=mytree.getIndexes("B");//v=[0,2]
//vector<int>v = mytree.getIndexes("");//v=[0,1,2,3]
//vector<int>v = mytree.getIndexes("S");//v=[3]
system("pause");
return 0;
}