KMP学习更新日志
题目链接
题意:
给你一串字符串,我们要找到这样的一串子字符串,让他满足既是前缀又是后缀,并且还在中间出现过的最长子字符串,如果没有就输出题目给的那一串东西。
因为我们知道前缀的next[]开始都是从0开始的,所以我们可以不考虑它,然后从后缀看,后缀的next[]不能为0,因为那样就说明不存在这样的答案,所以,我们知道的是后缀肯定在不为0的情况下才有解的可能,接下来,我们向前看,看看中间的字符串是否有等next[]值的点,有的话,那么它一定是最优解,那么,我们怎么确定是否存在呢?用到了STL中的set来处理这样的问题,我们把1~len-1的所有next[]解的值都存进去,这里不存终点的是因为我们利用的是终点的值来推的,所以不能存终点,然后我们从终点开始向前回溯,遇到set.count()存在的话就是可行解,输出就是了,不然搜完后还是没有就直接输出题目中给出的那组。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=1e6+5;
char a[maxN];
int len, nex[maxN];
set<int> st;
void cal_next()
{
nex[0] = nex[1] = 0;
int k = 0;
for(int i=2; i<=len; i++)
{
while(k>0 && a[k+1]!=a[i]) k=nex[k];
if(a[k+1] == a[i]) k++;
nex[i]=k;
}
}
int main()
{
while(scanf("%s", a+1)!=EOF)
{
getchar();
len=(int)strlen(a+1);
cal_next();
st.clear();
int tmp = nex[len];
for(int i=1; i<len; i++) st.insert(nex[i]);
bool flag=false;
while(tmp>0)
{
if(st.count(tmp))
{
flag=true;
for(int i=1; i<=tmp; i++) printf("%c", a[i]);
printf("\n");
break;
}
tmp=nex[tmp];
}
if(!flag) printf("Just a legend\n");
}
return 0;
}