最长的回文串——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

#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
",max-1);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/huhuuu/p/3298005.html