一道KMP模板题,先要理解next的概念
概念在网上有很多,我就不说了,说下next为什么能解决这道题
get_next()写正确后输入str
next[i]的含义在于:字符串中[0, next[i]-1] == [i-next[i], i-1]
[0, next[i]-1]的含义为字符串中下标0到next[i]-1组成的子串
对应于上面的样例有:
next[18] = 9: [0, 8] == [9, 17] == "ababcabab"
next[9] = 4: [0, 3] == [5, 8] == "abab"
next[4] = 2: [0, 1] == [2, 3] == "ab"
next[2] = 1: [0, 0] == [1, 1] == "a"
现在我们根据上面的依据证明这道题的答案即为
i, next[i], next[next[i]] ...
1、对于上面的字符串str,明显有str == str,所以str.size()即18满足条件
2、next[str.size()] = next[18] = 9,因为有[0, 8] == [9, 17],所以9满足条件
3、next[9] = 4,因为有[0, 3] == [5, 8],而[0, 8] == [9, 17]可以推出 [5, 8] == [14, 17],所以[0, 3] == [14, 17],所以4满足条件
4、next[4] = 2,因为有[0, 1] == [2, 3],而[0, 3] == [5, 8]可以推出[2, 3] == [7, 8],又有[0, 8] == [9, 17]可以推出[2, 3] == [16, 17],所以[0, 1] == [16, 17]满足条件,所以2满足条件
5、next[2] = 1,因为篇幅比较长,同上证明就行了
所以这道题的代码如下:
#include <cstdio>
#include <cstring>
#define MAXN 400100
using namespace std;
int next[MAXN], ans[MAXN];
char str[MAXN];
void get_next(char p[]) {
int len = strlen(p);
int i = 0, j = -1;
next[0] = -1;
while(i < len) {
if(j == -1 || p[i]==p[j]) {
++i, ++j;
next[i] = j;
} else j = next[j];
}
}
int main(void) {
int len;
while(scanf("%s", str) != EOF) {
get_next(str);
len = strlen(str);
int cnt = 0;
int i = len;
while(next[i] > 0) {
ans[cnt++] = i;
i = next[i];
}
ans[cnt++] = i;
printf("%d", ans[cnt-1]);
for(int i=cnt-2; i>=0; --i)
printf(" %d", ans[i]);
puts("");
}
return 0;
}