CodeForces 126B Password

题目

传送门

解法

考虑使用 \(\mathtt {kmp}\)。我们先枚举 \(i\)(除了 \(1\)\(n\),也即避免前缀与后缀的情况),将 \(nxt_i\) 打上标记,这意味着长度为 \(nxt_i\) 的串可以为前缀与中间串。

再考虑后缀。从 \(n\) 开始,用 \(nxt\) 一个一个地跳,相当于跳与前缀匹配的后缀。我们找到第一个被标记的 \(nxt\) 就是最长的串。

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>

const int N = 1000010;

int n, nxt[N];
bool vis[N];
char s[N];

int read() {
	int x = 0, f = 1; char s;
	while((s = getchar()) > '9' || s < '0') {
		if(s == '-') f = -1;
		if(s == EOF) exit(0);
	}
	while(s >= '0' && s <= '9') {
		x = (x << 1) + (x << 3) + (s ^ 48);
		s = getchar();
	}
	return x * f;
}

void init() {
	int j = 0;
	for(int i = 2; i <= n; ++ i) {
		while(j && s[i] != s[j + 1]) j = nxt[j];
		if(s[i] == s[j + 1]) ++ j;
		nxt[i] = j;
	}
}

int main() {
	scanf("%s", s + 1); n = strlen(s + 1);
	init();
	for(int i = 2; i < n; ++ i) vis[nxt[i]] = 1;
	vis[0] = 0;
	for(int i = n; i; i = nxt[i])
		if(vis[nxt[i]]) {
			for(int j = 1; j <= nxt[i]; ++ j) putchar(s[j]);
			putchar('\n'); return 0;
		}
	puts("Just a legend");
	return 0;
}
原文地址:https://www.cnblogs.com/AWhiteWall/p/12337012.html