还是KMP,我觉得应该把自己的心得写一下。这题要求的是“前后辍”,即既是前辍又是后辍,比如“abcab”中的“ab”。KMP求next数组有两种算法,一种是:

if(t[i] == t[j])

{ i++; j++; next[i] = j; }

另一种是:

if(t[i] == t[j])

{ i++; j++;

  if(t[i] != t[j])

    next[i] = j;

  else

    next[i] = next[j];

}

第二种是第一种的改进版,不过这一题恰恰是第一种比较合适。对字串“ababcabab”来说,两种方法构造的next分另为:

a b a b c a b a b  
-1 0 -1 0 2 -1 0 -1 0 4
-1 0 0 1 2 0 1 2 3

4

 

 

 

 

 

在文中插表格太麻烦,我就做成这样了。上一行是第二种,下一行是第一种方法,从左到右分别为next[0]到next[10],第一种方法的数组满足这样的性质:对任意 i ,next[i] = j 表示字串中前 i 个字符组成的子串的最长“前后辍”长度为 j 。比如,‘c’ 对应着next[4] = 2,那么前4个字符“abab” 的最长前后辍“ab”的长度为2。这样就好办多了,“ababcabab” 的最长串为“abab”,“abab”的最长串为“ab”,递归打印就行了。

复制代码
 1 #include <stdio.h>
 2 #include <string.h>
 3 int next[1000005],len;
 4 char T[1000005];
 5 void getnext(char *t)
 6 {
 7     int i=0,j=-1;
 8     len = strlen(T);
 9     next[0] = -1;
10     while(i < len)
11         if(j == -1 || T[i]==T[j])
12         {
13             i++;j++;
14             next[i] = j;
15         }
16         else j = next[j];
17 }
18 void show(int a)
19 {
20     if(next[a])
21         show(next[a]),
22         printf(" %d",a);
23     else printf("%d",a);
24 }
25 int main()
26 {
27     while(~scanf("%s",T))
28     {
29         getnext(T);
30         show(len);
31         printf("\n");
32     }
33     return 0;
34 }
复制代码

 

PS:刚刚才发现,第二种数组虽不对任意 i 满足上述性质,但是在这一题相应的位置上是满足的,晕死,那不就是两种都可以了。