HDU 3068 最长回文(manacher算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068

题意:求最长回文串。

思路:

将串之间插入串中没有出现过的字符,这样不管原来的串的长度是奇数还是偶数现在都是奇数。以下我们都是针对新的串而言。设rad[i]表示以位置i为中心,半径为rad[i]的串为回文串,即S[i-rad[i],i-1]=S[i+1,i+rad[i]]。现在我们假设已经求出了0到i位置的rad值,现在用i位置的rad值求后面的位置i+k的rad值,

HDU 3068 最长回文(manacher算法)_第1张图片

HDU 3068 最长回文(manacher算法)_第2张图片

HDU 3068 最长回文(manacher算法)_第3张图片



char s1[N];
int rad[N],len;


//最长回文串
//串str,长度len(str[0]~str[len-1])
//回文串的起始位置start和长度sum
//rad[i]表示i位置回文串的半径
char s[N];
void manacher(char s1[],int len,int &start,int &sum,int rad[])
{
    int i,j=0,k;
    FOR0(i,len) s[j++]='#',s[j++]=s1[i];
    s[j++]='#'; len=2*len+1; i=0,j=1;
    clr(rad,0);
    while(i<len)
    {
        while(i-j>=0&&i+j<len&&s[i-j]==s[i+j])j++;
        rad[i]=j-1;
        k=1;
        while(k<=rad[i]&&rad[i]-k!=rad[i-k])
        {
            rad[i+k]=min(rad[i-k],rad[i]-k);
            k++;
        }
        i+=k;
        j=max(j-k,0);
    }
    int ans=0,pos;
    for(i=0;i<len;i++) if(rad[i]>ans)
    {
        ans=rad[i];
        pos=i;
    }
    sum=ans;
    start=pos/2-ans/2;
}

int main()
{
    while(scanf("%s",s1)!=-1)
    {
        int start,ans;
        len=strlen(s1);
        manacher(s1,len,start,ans,rad);
        PR(ans);
    }
    return 0;
}

  

你可能感兴趣的:(HDU)