字尾樹的定義
字尾樹(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...