题意:
Problem Description
女神邀请众ACdream开联欢会,显然作为ACM的佼佼者,气球是不能少的~。女神准备了三种颜色的气球,红色,黄色,绿色(交通信号灯?)
有气球还不能满足女神,女神要在气球上写字。
写什么好呢~?字符串神马的最有爱了~
女神先拿出一个字符串,然后把字符串的每一个真·前缀写到了黄色气球上面,每一个真·后缀写到了绿色气球上面,每一个真·子串写到了红色气球上面。
对于一个字符串s[1…n],真·前缀为s1…i·,真·后缀为sj…n,真·子串为si…j
于是女神就得到了好多好多的气球~
那么在同时出现在三种颜色的气球上的字符串中,最长是什么?
神马,404 not found? 找不到这样的字符串?女神很生气!那就只好输出”angry goddess”了。(不包括双引号,注意大小写,中间有一个空格)
Input
多组数据,每组数据一行字符串,长度不超过100000,
Output
对于每组数据,输出一个字符串
Sample Input
abcabcabc
aaaaaaaaa
abcabc
Sample Output
abc
aaaaaaa
angry goddess
Hint
对于样例2,由于aaaaaaaa不是真子串,因此不会出现在红色气球上面
对于样例3,由于abc是真前缀,真后缀,但不是真子串,所以找不到这样的字符串
题解:先用kmp算法得到next数组,就可以知道前i个字符前缀和后缀相同的字符串长度,先可以得到next[len]是最大可能解,然后扫描位置2到位置len-1的next数组是否能得到相同的长度next[len],说明是存在相同中缀,找不到就继续找next[next[len]],缩小长度再扫描,直到next[temp] == 0。
#include <stdio.h>
#include <string.h>
const int N = 100005;
char str[N];
int next[N], len;
void get_next() {
int pp = -1, k = 0;
next[0] = -1;
while (k < len) {
if (pp == -1 || str[pp] == str[k]) {
k++;
pp++;
next[k] = pp;
}
else
pp = next[pp];
}
}
int main() {
while (scanf("%s", str) != EOF) {
len = strlen(str);
get_next();
int temp = len, res = -1;
while (next[temp]) {
for (int i = 1; i <= len - 1; i++)
if (next[i] == next[temp]) {
res = next[temp];
break;
}
if (res != -1)
break;
temp = next[temp];
}
if (res == -1)
printf("angry goddess\n");
else {
for (int i = 0; i < res; i++)
printf("%c", str[i]);
printf("\n");
}
}
return 0;
}