求最长回文串(Manacher算法)

O(n)效率的字符串求最长回文串,感觉这个blog上写的很详细:http://www.open-open.com/lib/view/open1419150233417.html

有几个要点:

1、先要将字符串扩展成2*l+1长度的,在每两个字符之间要加上一个用不到的字符,比如‘#’,方便处理偶数回文串。

2、在扩展后的字符串两端要加一些特殊字符,防越界。

3、ra[i]数组表示以i为中点的最长回文串,mx表示以j(1<=j

(证明ra[i]-1即为原字符串的回文串的长度的证明:http://wenku.baidu.com/view/3031d2d3360cba1aa811da42.html)

代码附上

#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1000012;
char s[maxn];
char tmp[maxn<<1];
int ra[maxn<<1];
int INIT(char *st)
{
    int i,len=strlen(st);
    tmp[0]='@';
    for (i=1;i<=2*len;i+=2)
    {
        tmp[i]='#';
        tmp[i+1]=st[i/2];
    }
    tmp[2*len+1]='#';
    tmp[2*len+2]='$';
    tmp[2*len+3]=0;
    return 2*len+1;
}
int MANACHER(char *st,int len)
{
    int mx=0,ans=0,po=0;
    for (int i=1;i<=len;i++)
    {
        if (mx>i)
            ra[i]=min(mx-i,ra[2*po-i]);
        else  ra[i]=1;
        while (st[i-ra[i]]==st[i+ra[i]]) ra[i]++;
        if (ra[i]+i>mx)
        {
            mx=ra[i]+i;
            po=i;
        }
        ans=max(ans,ra[i]);
    }
    return ans-1;
}
int main()
{
    int T;
    scanf("%d",&T);
    getchar();
    while (T--)
    {
        int ans,l;
        gets(s);
        l=INIT(s);
        printf("%d\n",MANACHER(tmp,l));
    }
    return 0;
}

可以去hihoCoder 1032交:https://hihocoder.com/problemset/problem/1032

你可能感兴趣的:(字符串处理)