kuangbin专题16H(next数组)

题目链接: https://vjudge.net/contest/70325#problem/H

 

题意: 输入字符串 str, 求 str 子串中既是 str 前缀又是 str 后缀的的字符串长度, 按照升序输出.

 

思路: 先求个 next 数组, next[i] 为以 i - 1(字符串下标从0开始) 字符为后缀的字符串与以第一个字符为前缀的字符串的最大匹配长度.

首先 str 本身是满足条件的. 然后再不断用 next[len] 迭代 len 即可. len 的初始值为 str 的长度. 由 next 的性质可以知道以 next[len] - 1 为后缀的字符串会和以 len - 1 为后缀的字符串重合, 那么所有迭代到的子串都会和以 str 最后一个字符为后缀的字符串重合. (可以参考下面的图) 那么现在前后缀条件都满足啦.

图是从 http://www.cnblogs.com/dongsheng/archive/2012/08/13/2636261.html 偷过来的....

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 
 6 const int MAXN = 4e5 + 10;
 7 int nxt[MAXN], vis[MAXN], len;
 8 char str[MAXN];
 9 
10 void get_nxt(void){
11     memset(nxt, 0, sizeof(nxt));
12     int i = 0, j = -1;
13     nxt[0] = -1;
14     while(i < len){
15         if(j == -1 || str[i] == str[j]) nxt[++i] = ++j;
16         else j = nxt[j];
17     }
18 }
19 
20 int main(void){
21     while(~scanf("%s", str)){
22         len = strlen(str);
23         int cnt = 0;
24         get_nxt();
25         vis[cnt++] = len;
26         while(nxt[len] > 0){
27             len = nxt[len];
28             vis[cnt++] = len;
29         }
30         for(int i = cnt - 1; i >= 0; i--){
31             printf("%d", vis[i]);
32             if(i) printf(" ");
33         }
34         puts("");
35     }
36     return 0;
37 }
View Code

 

posted @ 2017-08-10 20:32  geloutingyu  阅读(149)  评论(0编辑  收藏  举报