1. 程式人生 > >利用字尾陣列求最長的重複子串

利用字尾陣列求最長的重複子串

字尾是指從某個位置 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);
}