时间:2014.09.12
地点:基地
心情:明天就要和欧阳去武汉面试阿里了,整理一下同学求助的一道题,写下这一篇,愿一切顺利。
一、题目:
求一个字符串中连续出现最多的子串次数:例如字符串abcbcbcabc,连续出现次数最多的子串是bc,出现次数为3。
二、分析
方法:后缀思路
比如题目中举例中的字符串,它的后缀有:
abcbcbcabc 0
bcbcbcabc 1
cbcbcabc 2
bcbcabc 3
cbcabc 4
bcabc 5
cabc 6
abc 7
bc 8
c 9
容易看出,所求的那段字串bc等间隔性的出现在不同一系列后缀中,于是可从源字符串中取两个端点间的字串并规律性地和后缀中等距离的字串前缀比较,若是发生匹配则计数器加1,若是不匹配放continue进入下一轮。
举例来说:1.先从源串中即0号后缀中取出a,因为只取出一个字符,所以若重现,则紧接着的1号后缀首字符也应该是,与之比较,a!=b,计数器保持为1,接着取ab,现在有两个字符,若重复,则在2号后缀前两个字符应该匹配,ab!=cb,匹配失败,计数器保持为1...如此重复,当右端点其实到达源串中点位置时即可打止,避免之后不必要的计算了。当取bc时,会和3号5号后缀前两字符发生匹配,计数器相应加1,且更新最大值,等等,最后得出结论:
三、代码
size_t GetMaxRepeatSubLen(const string& str)
{
size_t max_len = 1;
size_t str_len = str.length();
for (size_t i = 0; i < str_len; ++i)
{
for (size_t j = i + 1; j < str_len/2; ++j)
{
string pattern = str.substr(i, j - i);
if (pattern == str.substr(j, j - i))
{
size_t offset = j - i;
int count = 2;
for (size_t k = j + offset; k < str_len; k += offset)
{
if (pattern == str.substr(k, offset))
count += 1;
else
break;
if (count>max_len)
max_len = count;
}
}
}
}
return max_len;
}