链接:https://www.nowcoder.com/acm/contest/77/C
来源:牛客网
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
有一个字符串 让你找到这个字符串 S 里面的子串T 这个子串 T 必须满足即使这个串的前缀 也是这个
串的后缀 并且 在字符串中也出现过一次的(提示 要求满足前后缀的同时也要在字符串中出现一次 只是前后缀可不行 输出最长满足要求字符串)
串的后缀 并且 在字符串中也出现过一次的(提示 要求满足前后缀的同时也要在字符串中出现一次 只是前后缀可不行 输出最长满足要求字符串)
输入描述:
给出一个字符串 长度 1 到 1e6 全部是小写字母
输出描述:
如果找的到就输出这个子串T 如果不行就输出 Just a legend
示例1
输入
fixprefixsuffix
输出
fix
示例2
输入
abcdabc
输出
Just a legend方法一:kmp:注意枚举的模式串,以及原串与给定字符之间的差别:
#include <iostream> #include <cstring> #include <cstdio> using namespace std; string str, mo; int Next[1000005]; void getNext(){ Next[0] = -1; //一定要初始化 int i = 0, j = -1, len = mo.length(); while(i < len){ if(j == -1 || mo[i] == mo[j]) //j表示前i-1个字符中前缀和后缀相等的长度 Next[++i] = ++j; //如果跳转的值相同,则Next的下一位对应的为前一位加一 else j = Next[j]; //j回溯 } } int kmp(){ int ans = 0; int i = 0, j = 0, l1 = str.length(), l2 = mo.length(); while(i < l1){ if(j == -1 || str[i] == mo[j]) i++, j++; else j = Next[j]; //只需回溯j if(j == l2) //在原串中找到一个模式串 ans++; } return ans; } int main(){ ios::sync_with_stdio(false); //取消cin 与 scanf()同步,刚刚没加超时了 string tt; cin >> tt; int len = tt.length(), flag = 1; for(int i = len - 2, j; i >= 1; i--){ //枚举所以可能的前缀长度,注意不是范围不是0~len/2,要保证中间子串不用前缀后缀重合即可 string s; for(j = 0; j < i; j++){ //判断是否与后缀相等 if(tt[j] != tt[len - i + j]){ break; } s += tt[j]; } if(j == i){ mo = s; //将前缀作为模式串 getNext(); // str = tt; for(int k = 1; k < len - 1; k++) //中间不与前缀后缀重合的子串作为原串,注意范围!!! str += tt[k]; int ct = kmp(); if(ct >= 1){ //在原串中找到即可 cout << s << endl; flag = 0; break; } str.clear(); } } if(flag){ cout << "Just a legend" << endl; } return 0; } /* aaaaa 结果: aaa */
第二次写:
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int Next[1000005]; void getNext(string p){ int j = 0, k = -1, len = p.length(); Next[0] = -1; while(j < len){ if(k == -1 || p[j] == p[k]){ /* Next[++j] = ++k; //换成下面的if和else */ if(p[++j] == p[++k]){ Next[j] = Next[k]; } else{ Next[j] = k; } } else{ k = Next[k]; } } } int main() { string str, p, pp; cin >> str; int len = str.length(); int ct = 0, k = 1; while(k < len - 1){ p = str.substr(0, k); pp = str.substr(len - k, k); if(p != pp){ k++; continue; } getNext(p); int count = 0, i = 0, j = 0; while(i < len){ if(j == -1 || str[i] == p[j]){ j++, i++; } else{ j = Next[j]; } if(j == k){ count++; j = 0; i = i - k + 1; if(count >= 3){ ct = k; break; } } } k++; } if(ct == 0){ cout << "Just a legend" << endl; } else{ cout << str.substr(0, ct) << endl; } return 0; }
方法二:用substr,find:
#include<iostream> #include<cstring> #include <string> using namespace std; string s; int main(){ cin >> s; int k = 1, l = s.size(); string ans = ""; while (l>2 && k<l){ string ss = s.substr(0, k);//拷贝s第0个数开始,长度为k if (s.substr(l - k, k) == ss) { string sss = s.substr(1, l - 2); ///cout << sss.find(ss) << endl; if (sss.find(ss)<l - 2) ans = ss; } k++; } if (ans == "") cout << "Just a legend" << endl; else cout << ans << endl; }
来源:https://www.cnblogs.com/zhumengdexiaobai/p/8471244.html