题目大意:
有一只聪明的小猫擅长给新生儿取名字,它取名字的算法依据如下,先将父母的名字连接成一个新的字符串,然后从这个字符串中寻找其实前缀又是后缀的字符串,将该字符串作为孩子的名字(可能会有好几个这样的字符串)。
现有多个测例(测例数题中给出),每个测例都会给以个字符串,长度为[1, 400000],对于每个测例打印出所有可能的前后缀字符串的长度,按照递增序列打印出来。
注释代码:
/*
* Problem ID : POJ 2752 Seek the Name, Seek the Fame
* Author : Lirx.t.Una
* Language : C
* Run Time : 110 ms
* Run Memory : 3632 KB
*/
#include <string.h>
#include <stdio.h>
//注意:next数组所记录的正好就是既是前缀又是后缀的字符串
//next[len]为最长的前后缀字符串的末尾下标
//next[ next[len] ]即为第二场的前后缀字符串的末尾下标
//因此类推可以用递归找出所有前后缀字符串
//递归结尾就是下标为0
//由于下标是从1开始计的,因此下标就等于前后缀字符串的长度
#define MAXLEN 400002
char s[MAXLEN];//string
int nxt[MAXLEN];
void
bd_nxt(int len) {
int i, j;
nxt[1] = 0;
for ( j = 0, i = 2; i <= len; i++ ) {
while ( j > 0 && s[j + 1] != s[i] )
j = nxt[j];
if ( s[j + 1] == s[i] )
j++;
nxt[i] = j;
}
}
void
out(int x) {//递归打印数组长度
if ( !nxt[x] ) {
printf("%d ", x);
return ;
}
out( nxt[x] );
printf("%d ", x);
}
int
main() {
int len;//字符串长度
while ( ~scanf("%s", s + 1) ) {
len = strlen(s + 1);
bd_nxt(len);
out(len);
putchar('\n');
}
return 0;
}
无注释代码:
#include <string.h>
#include <stdio.h>
#define MAXLEN 400002
char s[MAXLEN];
int nxt[MAXLEN];
void
bd_nxt(int len) {
int i, j;
nxt[1] = 0;
for ( j = 0, i = 2; i <= len; i++ ) {
while ( j > 0 && s[j + 1] != s[i] )
j = nxt[j];
if ( s[j + 1] == s[i] )
j++;
nxt[i] = j;
}
}
void
out(int x) {
if ( !nxt[x] ) {
printf("%d ", x);
return ;
}
out( nxt[x] );
printf("%d ", x);
}
int
main() {
int len;
while ( ~scanf("%s", s + 1) ) {
len = strlen(s + 1);
bd_nxt(len);
out(len);
putchar('\n');
}
return 0;
}
单词解释:
seek:vt, 寻找,寻求
fame:n, 名声,名望
tramp:n, 流浪者; vt, 流浪,踩踏,踩(走过)
hill:n, 小山,丘陵
dale:n, 山谷,排水口
newly-born:adj, 新生的
innovative:adj, 革新的,创新的
prefix:n, 前缀
suffix:n, 后缀