利用字尾陣列求最長的重複子串
字尾是指從某個位置 i 開始到整個串末尾結束的一個特殊子串,可表示為suffix[i]
字尾陣列是i從0變化到n-1,由suffix[i]所形成的陣列。
如字串 banana
該字串產生的字尾陣列為:
suffix[0]:banana
suffix[1]:anana
suffix[2]:nana
suffix[3]:ana
suffix[4]:na
suffix[5]:a
利用字尾陣列求最長重複子串的步驟:
1、對待處理的字串產生字尾陣列
2、對字尾陣列排序
3、依次檢測相鄰兩個字尾的公共長度
4、取出最大
(由於對所有子串進行排序,這樣可以把相同的子串排在一起。對於一個子串,一個與其重複最多的子串肯定是緊挨著自己的兩個子串)
例如對banana的字尾陣列:進行快速排序,以將字尾相近的(變位詞)子串集中在一起 a[0]:a
a[1]:ana
a[2]:anana
a[3]:banana
a[4]:na
a[5]:nana
之後可以依次檢測相鄰兩個字尾的公共長度並取出最大公共的字首。得到最長重複子串為ana。
程式如下:
string LongestRepeatedSubstr(string s)
{
int len = s.length();
//構造字尾陣列
vector<string> suffix;
for(int i = 0; i < len; i++)
suffix.push_back(s.substr(i));
//對字尾陣列進行排序
sort(suffix.begin(), suffix.end());
//統計相鄰字尾的公共長度,並儲存最大公共長度,及對應子串位置
int maxLen = 0;
int pos = 0;
for(int i = 0; i < len-1; i++)
{
string substr1 = suffix[i];
string substr2 = suffix[i+1];
int tempLen = 0;
for(int j = 0; j < substr1.length() && j < substr2.length(); j++)
{
if(substr1[j] == substr2[j])
tempLen++;
else
break;
}
if(tempLen > maxLen)
{
maxLen = tempLen;
pos = i;
}
}
return suffix[pos].substr(0, maxLen);
}