poj_2752 Seek the Name, Seek the Fame

来源:互联网 发布:野兽派有淘宝店吗 编辑:程序博客网 时间:2024/06/05 10:51

http://poj.org/problem?id=2752



分析:

       题目要求一个既是S的前缀又是S的后缀的子串(S本身是自己的前缀又是自己的后缀)。主要利用next数组求解。

      e.g.

no

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

S

a

b

a

b

c

a

b

a

b

a

b

a

b

c

a

b

a

b

/0

next

-1

0

0

1

2

0

1

2

3

4

3

4

3

4

5

6

7

8

9


      Out: 2  4  9  18
      由于子串既是S的前缀又是后缀,所以除去字符串本身长度18外,次长的为在字符串结束符‘\0’处求得的next数组值9,

      此时S的前缀为 ababcabab(012345678),S的后缀为 ababcabab(9-17)。接着找第三长的既是S的前缀又是S后缀的子串。

      如果找next[17]处的值8,则不满足是S后缀的要求,因为17本身的字符是被排除在外的,10-16亦是同理。

      而对于9之前的子串有next[18]知既是S的前缀又是S的后缀。而next[9]的值4指明了位置在9前的子串的前后缀长度为4,

      而该子串包含在S的前缀中,所以该子串的后缀也包含在S的前缀中,而S的前缀又是S的后缀,所以该子串的后缀也是S的后缀。

      依次往前直到满足条件的子串长度为0为止。


代码:

      

//seek the name,seek the fame#include <iostream>#include <stdio.h>#include <string.h>#include <string>using namespace std;#define MAXN 400004int plen;int next[MAXN];    //MAXN模式串长度char pat[MAXN];void getNext(){int j=0, k=-1;next[0]=-1;while(j<plen){   //计算模式串每一个位置j的next[j]值while(k>-1 && pat[j]!=pat[k])  k=next[k];next[++j]=++k;}}void show(int n){    if(next[n]>0){        show(next[n]);        printf("%d ",next[n]);    }}int main(){    //freopen("in.txt","r",stdin);    while(cin>>pat){        plen=strlen(pat);        getNext();        show(plen);        cout<<plen<<endl;    }    return 0;}

0 0