• 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);
        }
    }
  • 相关阅读:
    Codeforces Round #692
    【kuangbin专题一】简单搜索
    B. Beam Cannon【2014上海邀请赛】
    E. Maze【2014上海邀请赛】
    策略模式 Strategy -- 学习HeadFirst设计模式记录
    状态模式 State -- 学习HeadFirst设计模式记录
    迭代器模式 Iterator,组合模式 Composite -- 学习HeadFirst设计模式记录
    命令模式 Command – 学习HeadFirst设计模式记录
    单例模式Singleton – 学习HeadFirst设计模式记录
    工厂模式Factory – 学习HeadFirst设计模式记录
  • 原文地址:https://www.cnblogs.com/liyexin/p/13965673.html
Copyright © 2020-2023  润新知