最长的回文串——hdu3068

http://acm.hdu.edu.cn/showproblem.php?pid=3068

abcba 5

aab 2

在一个字符串里寻找一条最长的回文串

比较直接的想法是枚举中心点 然后像两边扩散,但这样不仅要考虑最长子串的奇数偶数情况,而且时间复杂度会很高,因为会有比较多的重复计算

分析 aaaab, abcba

变成 #a#a#a#a#b# ,    #a#b#c#b#a#

就都成了奇数子串

现在再用一个数组P保存到该点的最长回文

#a#a#a#a#b#

12345432131

if( mx > i )
p[i] = min( p[2*id-i], mx-i ); 

这一句减少了重复计算过程

至于为什么要取小,考虑

abcbabc

最长的回文串——hdu3068
#include<stdio.h>

#include<string.h>



char ss[400999];

char ne[400999];

int p[409999];

int len;



int min(int a,int b){

    return a>b?b:a;

}



void pre()

{

    int i,n2;

    len=strlen(ss);

    n2=len*2;

    for(i=0;i<=n2;i++){

        p[i]=0;

    }

    ne[0]='#';

    for(i=0;i<len;i++){

        ne[2*i+1]=ss[i];

        ne[2*i+2]='#';

    }

    ne[2*len+1]='@';//end

} 



int cal(){

    int i,max=0;

    int id;

    int n=len*2;

    int mx = 0;



    for(i=1; i<n; i++)

    {

        if( mx > i )  

            p[i] = min( p[2*id-i], mx-i );        

        else

            p[i] = 1;

        for(; ne[i+p[i]] == ne[i-p[i]]; p[i]++)

            ;

        if( p[i] + i > mx )

        {

            mx = p[i] + i;

            id = i;

        }

    }



    for(i=1;i<n;i++){

        if(p[i]>max)max=p[i];

    }



    return max;

}



int main()

{

    int n2,i,max=0,p;

    while(scanf("%s",ss)!=EOF){

        pre();max=cal();

        printf("%d\n",max-1);

    }

    return 0;

}
View Code

 

 

你可能感兴趣的:(HDU)