题目内容:
馅饼同学是一个在百度工作,做用户请求(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; }