后缀是指从某个位置 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);
}