现在的位置: 首页 > 算法 > 正文

poj 2752 Seek the Name, Seek the Fame (KMP)

2018年09月22日 算法 ⁄ 共 795字 ⁄ 字号 评论关闭

题目链接:   poj 2752

题目大意:   给出字符串,找出所有的前缀和后缀相等的子串

                  按小到大输出这些子串的长度
解题思路:  
            
                  如图所示,根据next[  ]前缀的性质左边有颜色部分右边有颜色部分完全相等
                  因为左边的红色和右边的红色相等,如果左边的红色和左边的绿色相等,则左边的红色必定与右边的绿色相等
                  既左红+左蓝+左绿和左绿是我们要求的子串
                  根据这个规律不断地递推下去,所有的子串都可以求出来
代码:
//Final  KMP变形,找出所有字符串的子串的长度,子串满足既是前缀又是后缀(可以重叠)
#include <stdio.h>
#include <string.h>
#define MAX 410000
char ch[MAX];
int Tlen,next[MAX],ans[MAX];

void Get_next()       //求字符串的next[]前缀数组
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<Tlen)
    {
        if(j==-1||ch[i]==ch[j])
        {
            i++; j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
}

int main()
{
    int i,n;
    while(scanf("%s",ch)!=EOF)
    {
        n=0;
        Tlen=strlen(ch);
        memset(next,0,sizeof(next));
        Get_next();
        ans[0]=Tlen;          //本身也是
        n=0; i=Tlen;
        while(next[i]>0)      //根据next[]性质求出所有满足题意的长度
        {
            ans[++n]=next[i];
            i=next[i];
        }
        for(i=n;i>=0;i--)
        {
            printf("%d",ans[i]);
            if(i!=0)
                printf(" ");
        }
        printf("\n");
    }
    return 0;
}

抱歉!评论已关闭.