Acwing 139. 回文子串的最大长度(前缀+后缀处理+哈希+二分)

地址:https://www.acwing.com/problem/content/141/

解析:

1:在假设完全无差错的情况下,不同子串对应不同哈希值。

对于abcba,那么ab的哈希值应该等于ba的反转哈希值。

也就是说,根据一个字符串,迅速求出它的逆序字符串的反哈希值,如果两者相等,则两者为正逆序的关系。

所以要处理两个哈希,一个前缀哈希和一个后缀哈希。

2:每次处理一个串,它分两种情况,长度为偶数和奇数,很明显,奇数的时候,我们只需要根据中点 ,就可以直接判断以它为中点的两个半径是否相等。而偶数相对麻烦一点,所以考虑把字符串括一下,每两个字符之间加入同一个26个字母之外的一个字符('z'+1即可),这样,我们枚举所有包含原字母的串,它们都是奇数长度。(一个非常好的技巧~)

3:枚举每一个中点,二分半径,即可在O(nlogn)的复杂度下ac了。

#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<stack>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e6+10,P=131;//131 or 13331¾­ÑéÖµ 
ull hl[2*maxn],hr[2*maxn],p[2*maxn];
int le;
char st[2*maxn];
void init()
{
    p[0]=1;
    for(int i=1;i<=le;i++)//正缀
    {
        p[i]=p[i-1]*P;
        hl[i]=hl[i-1]*P+st[i]-'a'+1;
    }
    for(int i=le;i>=1;i--)//后缀
    {
        hr[i]=hr[i+1]*P+st[i]-'a'+1;
    }
}
ull checkl(int l,int r)
{
    return hl[r]-hl[l-1]*p[r-l+1];
}
ull checkr(int l,int r)
{
    return hr[l]-hr[r+1]*p[r-l+1];//因为与正缀求法是相反的。
}
int main()
{
    int ac=1;
    while(scanf("%s",st+1))
    {
        if(!strcmp(st+1,"END"))
            break;
        le=strlen(st+1);
        for(int i=2*le;i>=1;i-=2)//扩充
        {
            st[i]=st[i/2];
            st[i-1]='z'+1;
        }
        le=2*le;
        init();
        int maxx=0;
        for(int i=1;i<=le;i++)
        {
            int l=0 ,r=min(i-1,le-i);//最大半径
            while(l<r)
            {
                int md = l+r+1>>1;
                if(checkl(i-md,i-1)!=checkr(i+1,i+md))//如果不相等,则半径值大了,r=md-1让它变小。
                {
                    r=md-1;
                }
                else
                    l=md;
            }
            int ml=l*2+1;
            if(st[i+l+1]=='{'||i+l+1>le)  //根据尾部+1处判断实际长度,这个举个例子就可以推出
                ml=ml-ml/2;
            else
                ml=ml-ml/2-1;
            maxx=max(maxx,ml);
        }
        printf("Case %d: %d
",ac++,maxx);
    }
}
原文地址:https://www.cnblogs.com/liyexin/p/13965673.html