题目内容:
馅饼同学是一个在百度工作,做用户请求(query)分析的同学,他在用户请求中经常会遇到
一些很奇葩的词汇。在比方说“johnsonjohnson”、“duckduck”,这些词汇虽然看起来是一
些词汇的单纯重复,但是往往都是一些特殊品牌的词汇,不能被拆分开。为了侦测出这种词的
存在,你今天需要完成我给出的这个任务——“找出用户请求中循环节最多的子串”。
输入数据包括多组,每组为一个全部由小写字母组成的不含空格的用户请求(字符串),占一行。
用户请求的长度不大于100,000。
输出描述
对于每组输入,输出这组用户请求中循环节最多的子串。如果一个用户请求中有两个循环节数相同的
子串,请选择那个字典序最小的。
输入样例
duckduckgo
输出样例
duckduck
*/
//思路:通过每个字母去匹配后面的每个字母,若相同则判断这两个子母间是否是循环节,即从i到j-1是否和j到j + j - i相同,
//若相同则是循环节,则在d[i][j]填为1;如果有连续的循环出现则按长度推算d[i+(j-i)][j+(j-i)]也应该为1,可手绘图找规律
#include <iostream>
#include <cstring>
using namespace std;
string str, mu;
string maxstr;
int d[100][100];
int isxun(int i, int j){ //判断是否是循环
for(int k = i + 1, l = j + 1; k < j; k++, l++){
if(str[k] != str[l]){
return 0;
}
}
return 1;
}
int fun(string str){
int i, j = 0, flag = 0;
for(int i = 0; i < str.length(); i++){
for(int j = i + 1; j < str.length(); j++){ //暴力找循环节
if(str[i] != str[j]){
continue;
}
if(isxun(i, j)){
d[i][j] = 1;
}
}
}
}
string find(int i, int j){ //将(i,j)转化为字符串
string ss;
for(int k = i; k < j; k++)
ss += str[k];
return ss;
}
int main(){
int count = 0, max1 = 0, sum = 0;
cin >> str;
fun(str);
for(int i = 0; i < str.length(); i++){
for(int j = 0; j < str.length(); j++){
// cout << d[i][j] << " ";
if(d[i][j]){
count++;
sum = 0;
int len = j - i;
for(int k = i, l = j; k < str.length(), l < str.length(); k += len, l += len){
if(d[k][l]){ //相邻循环节间的关系,必定是i,j都相差一个循环节长度
sum++; //所以k,l的变化不是++;
d[k][l] = 0;
}
else
break;
}
sum += 1;
if(sum > max1){ //如果循环节数量比最大的长,则跟新最长的
max1 = sum;
maxstr = find(i, j);
// cout << maxstr << "sum: " << sum << " i:" << i << " j: " << j << endl;
}
else{ //如果循环节数量跟最长的一样,则跟判断字符串的字典序,若小于原串,则更新
string ff = find(i, j);
if(maxstr > ff && max1 == sum){
maxstr = ff;
max1 = sum; //不要忘记跟新max1
// cout << "QGQ: " << maxstr<< " sum= " << max1 << endl;
}
}
}
}
// cout << endl;
}
for(int i = 0; i < max1; i++)
cout << maxstr;
return 0;
}