程序员面试宝典-字符串中相同且长度最长子字符串及其位置
字符串中相同且长度最长子字符串及其位置
题目
题目:输入一行字符串, 找出其中出现的相同且长度最长的字符串, 输出它及其首字符的位置。
例如“yyabcdabjcabceg”, 输出结果应该为abc和3。
这个题目存在一个歧义,例如如果测试字符串为aaaaaa,我一开始以为结果是长度为3的aaa,原来正确答案是长度为5的aaaaa。即2个等长的子串可以有部分字符重叠。
第一种解法
原书中的题目是,可以重叠判断方式。
我没看懂书上的思路和代码实怎么对应的。这里根据代码的理解说一下他的思路。
这里是思路是从不同的位置开始截取不同长度的子字符串,然后分别正序和逆向寻找这个子字符串,
然后看找到这个字符串的位置是否相同,如果不同的话,则说明找到了一个满足的子字符串。
//书上的源代码,封装成函数形式,j的范围优化了一下,同时i的下限变成i>=1,其他不变
pair<int, string> fun(const string &str)
{
int count = 0;
string substr, tep;
int i, j, len = str.length();
//i表示要截取的长度(1-len - 1) j表示开始截取的位置 并且j循环的判断条件是 j <= len - i
for (i = len - 1; i >= 1; --i)
{
for (j = 0; j <= len - i; j++)
{
size_t t = 0;
size_t num = 0;
tep = str.substr(j, i);//从j开始 截取i个字符长度
t = str.find(tep);//从前开始找这个子串
num = str.rfind(tep);//从后开始找这个子串
//如果找到的两个数字位置不同 则进行更新和记录
if (t != num) {
count = t + 1;
substr = tep;
return make_pair(count, substr);
}
}
}
return make_pair(count, substr);
}
int main()
{
string str;
pair<int, string> rs;
while (cin >> str)
{
rs = fun(str);
cout << rs.second << ":" << rs.first << endl;
rs = fun1(str);
cout << rs.second << ":" << rs.first << endl;
}
return 0;
}
第二种解法
相同子串的首字符必定相等,因此依次遍历str的每个字符作为相等子串的首字符,然后在str中搜索与首字符相等的字符,然后从这两个相等的首字符开始,依次比较下一个字符是否相等,相等的话字符长度就会增加,直到下一个字符不等为止或者到了字符串的末尾。然后把这长度最大的值存放在maxlen中,最后返回长度最大的子串和起始字符的下标。
pair<int, string> fun1(const string& str)
{
int index = 0;
int maxlen = 0;
string substr;
int i = 0, j = 0;
int len = str.length();
int k = i+1;//表示i的下一个开始
int s, lt;
while (i<len)
{
j = str.find(str[i], k); //从(k~len-1)范围内寻找str[i]
if (j == string::npos)//若找不到,说明(k~len-1)范围内没有str[i]
{
i++;//i自增 表示换用下一个字符作为结果子串的开头假设
k = i + 1;
}
else
{ //若找到,则必有(j>=i+1)
s = i;//
lt = 1;//统计子串字符的长度
//从i的位置和j的位置同时开始往后判断
while (str[++s] == str[++j] && j<len) {}
lt = s - i;
if (lt>maxlen)
{
maxlen = lt;
substr = str.substr(i, lt);
index = i + 1;
}
k = j;
} //else
} //while
return make_pair(index, substr);
}
int main()
{
string str;
pair<int, string> rs;
while (cin >> str)
{
rs = fun(str);
cout << rs.second << ":" << rs.first << endl;
rs = fun1(str);
cout << rs.second << ":" << rs.first << endl;
}
return 0;
}