字尾樹的生成以及一些運用

2021-07-10 13:50:31 字數 4365 閱讀 9019

字尾樹的定義

字尾樹(suffix tree)是一種資料結構,能快速解決很多關於字串的問題。字尾樹的概念最早由weiner 於2023年提出,既而由mccreight 在2023年和ukkonen在2023年和2023年加以改進完善。

字尾,顧名思義,甚至通俗點來說,就是所謂字尾就是後面尾巴的意思。比如說給定一長度為n的字串s=s1s2..si..sn,和整數i,1 <= i <= n,子串sisi+1…sn便都是字串s的字尾。

以字串s=xmadamyx為例,它的長度為8,所以s[1..8], s[2..8], … , s[8..8]都算s的字尾,我們一般還把空字串也算成字尾。這樣,我們一共有如下字尾。對於字尾s[i..n],我們說這項字尾起始於i。

s[1..8], xmadamyx, 也就是字串本身,起始位置為1

s[2..8], madamyx,起始位置為2

s[3..8], adamyx,起始位置為3

s[4..8], damyx,起始位置為4

s[5..8], amyx,起始位置為5

s[6..8], myx,起始位置為6

s[7..8], yx,起始位置為7

s[8..8], x,起始位置為8

空字串,記為$。

字尾樹的結構

首先,說明一下字尾樹中的結構。在該程式中,定義了字尾樹的類,以及字尾樹的節點的類。節點的結構包括3個部分:1.節點的id.2.節點所存的字串。3.該節點的孩子指標。具體結構如下:

map

class

suffix_node

void insertstring(string s) //通過insertstring來將每乙個字尾插入樹中

else

child=child->children[s[0]];

i=compare(s,child->str);

}if(istr.length())}}

};class

suffix_tree

}~suffix_tree(){}

};

4.字尾樹的運用。

1. 查詢字串o是否在字串s中。

方案:用s構造字尾樹,按在trie中搜尋字串的方法搜尋o即可。

原理:若o在s中,則o必然是s的某個字尾的字首。

例如s: leconte,查詢o: con是否在s中,則o(con)必然是s(leconte)的字尾之一conte的字首.有了這個前提,採用trie搜尋的方法就不難理解了。 **如下:

int find_str(string t,string s)          //尋找字串s是否在字串t中

string str=s;

suffix_node* node=null;

int i;

node=tree.root->children[s[0]];

while(str.length()!=0)

else

}else

else}}

}

`

2.指定字串t在字串s中的重複次數。

方案:用s+』$』構造字尾樹,搜尋t節點下的葉節點數目即為重複次數

原理:如果t在s中重複了兩次,則s應有兩個字尾以t為字首,重複次數就自然統計出來了。**如下:

int num_leaf(suffix_tree tree,suffix_node* node)

else

}return number;

}int num_echo(string t,string s) //指定字串s在字串t中的重複次數

return num_leaf(tree,node);

}

3.字串s中的最長重複子串

方案:原理同2,具體做法就是找到最深的非葉節點。

這個深是指從root所經歷過的字元個數,最深非葉節點所經歷的字串起來就是最長重複子串。

為什麼要非葉節點呢?因為既然是要重複,當然葉節點個數要》=2。 **如下:

int is_leaf(suffix_node* node,suffix_tree tree)

string longest_echo_string(string t)

for(its=node->children.begin();its!=node->children.end();its++)}}

return long_str;

}

4.兩個字串s1,s2的最長公共部分

方案:將s1#s2

作為字串壓入字尾樹,找到最深的非葉節點,且該節點的葉節點既有#也有

(無#),**如下:

int has_$(suffix_node *node,suffix_tree tree)

for(i=0;iif(s[i]=='y')

num1--;

if(s[i]=='z')

num2--;

if(num1<=0&&num2<=0)

break;

}if(i>=s.length())

return

0; else

return1;}

string longest_common(string t,string s)

if(num==0&&has_$(node,tree))

}for(its=node->children.begin();its!=node->children.end();its++)}}

return long_str;

}

5.最後給乙個最終**:

#include 

#include

#include

#include

#include

using

namespace

std;

int num_node=0;

int compare(string a,string b)

return i;

}class suffix_node

void insertstring(string s)

else

child=child->children[s[0]];

i=compare(s,child->str);

}if(istr.length())}}

};class suffix_tree

}~suffix_tree(){}

};int find_str(string t,string s) //尋找字串s是否在字串t中

string str=s;

suffix_node* node=null;

int i;

node=tree.root->children[s[0]];

while(str.length()!=0)

else

}else

else}}

}int num_leaf(suffix_tree tree,suffix_node* node)

else

}return number;

}int num_echo(string t,string s) //指定字串s在字串t中的重複次數

return num_leaf(tree,node);

}int is_leaf(suffix_node* node,suffix_tree tree)

string longest_echo_string(string t)

for(its=node->children.begin();its!=node->children.end();its++)}}

return long_str;

}int has_$(suffix_node *node,suffix_tree tree)

for(i=0;iif(s[i]=='y')

num1--;

if(s[i]=='z')

num2--;

if(num1<=0&&num2<=0)

break;

}if(i>=s.length())

return

0; else

return1;}

string longest_common(string t,string s)

if(num==0&&has_$(node,tree))

}for(its=node->children.begin();its!=node->children.end();its++)}}

return long_str;

}int main()

運用C 的一些排序

include include using namespace std int main max element 找陣列中的最大數,返回指標型別 printf the max element is d n max element a,a 10 min element 找陣列中的最小數,返回指標型別 ...

一些簡單函式的運用

哈哈,最近學習到函式部分,下面一些簡單的小問題,我們試試來用函式的方法解決。1.輸出1 100之間的素數 include int main if j i return 0 上面是一般的方法,下面我們用函式的方法做 include include int number int i if j sqrt ...

一些結構體的運用例項

最近快要期末考試了,也沒什麼特別多時間去學習新的知識,只能好好複習一些學過的知識並加以運用。下面是一些例項 根據從易到難的順序排列 1.定義5個學生結構體型別 姓名 學號 三門課的成績 高數 英語 c語言 平均分 輸入該生的上述資訊並輸出。include typedef struct student...