程帅霞

不断受挫,不停起身,不断追寻,不止AC~~

导航

A - 最长回文(马拉车算法//manacher)

给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等

Input输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000Output每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input

aaaa

abab

Sample Output

4
3
https://www.cnblogs.com/csx-zzh/p/13445701.html

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define Max 110005
using namespace std;
char ma[Max*2];
int mp[Max*2];
void manacher(char s[],int len)
{
    int l=0;
    ma[l++]='$';
    ma[l++]='#';
    for(int i=0;i<len;i++)
    {
        ma[l++]=s[i];
        ma[l++]='#';
    }
    /*    a   b   a   b   c */
    /*$ # a # b # a # b # c # */
    ma[l]='\0';
    int mx,id;//mx为以id为中心的最长回文串的右界 id+p[id]=mx  [id-p[id]~mx] 
    //若遍历到i,有i<mx :if(i<mx) p[i]=min(p[j=2*id-i],mx-i) 
    for(int i=0;i<l;i++)
    {
        mp[i]=mx>=i?min(mp[2*id-i],mx-i):1;
        while(ma[i+mp[i]]==ma[i-mp[i]]) // 不需边界判断,因为左有'$',右有'\0'
            mp[i]++;//j 回文串左端正好与 id 的回文串左端重合时 
        // 我们每走一步 i,都要和 mx 比较,我们希望 mx 尽可能的远,这样才能更有机会执行 if (i < mx)这句代码,从而提高效率
        if(i+mp[i]>mx)//更新 id,mx;
        {
            mx=i+mp[i];
            id=i;
        }
    }
}

int main()
{
    while(~scanf("%s",s))
    {
        int len=strlen(s);
        int ans=0;
        manacher(s,len);
        for(int i=0;i<2*len+2;i++)
            ans=max(ans,mp[i]-1);//性质:最长回文长度=mp[i]-1; mp[i]个'#',mp[i]-1个字符,原长2*mp[i]-1; 
        printf("%d\n",ans);
    }
}

 

posted on 2020-08-06 12:32  程帅霞  阅读(146)  评论(0编辑  收藏  举报