zoukankan      html  css  js  c++  java
  • BZOJ2803[Poi2012]Prefixuffix——hash

    题目描述

    对于两个串S1、S2,如果能够将S1的一个后缀移动到开头后变成S2,就称S1和S2循环相同。例如串ababba和串abbaab是循环相同的。
    给出一个长度为n的串S,求满足下面条件的最大的L:
    1. L<=n/2
    2. S的L前缀和S的L后缀是循环相同的。

    输入

    第一行一个正整数n (n<=1,000,000)。第二行n个小写英文字母,表示串S。

    输出

    一个整数,表示最大的L。

    样例输入

    15
    ababbabababbaab

    样例输出

    6
     
    假设两个串是循环同构的,那么这两个串可以表示成x+y和y+x的形式(其中x,y为两个字符串)
    设f[i]表示前后都去掉i个字符后能匹配的最长前后缀长度,即y的最长长度。
    手画一下能够发现对于位于左一半的i和i+1,f[i]<=f[i+1]+2。如果大于了就说明f[i+1]还能更大。
    那么就可以从中间向开头转移f[i],最后求出i+f[i]的最大值即可。这道题卡自然溢出。
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll h[1000010];
    ll g[1000010];
    ll base1[1000010];
    ll base2[1000010];
    char ch[1000010];
    int mod=1e9+7;
    int n;
    int f[1000010];
    int ans=0;
    bool check(int x,int y,int l)
    {
        ll s1,s2,t1,t2;
        s1=((h[x+l-1]-h[x-1]*base1[l])%mod+mod)%mod;
        s2=((g[x+l-1]-g[x-1]*base2[l])%mod+mod)%mod;
        t1=((h[y+l-1]-h[y-1]*base1[l])%mod+mod)%mod;
        t2=((g[y+l-1]-g[y-1]*base2[l])%mod+mod)%mod;
        if(s1==t1&&s2==t2)
        {
            return true;
        }
        return false;
    }
    int main()
    {
        scanf("%d",&n);
        scanf("%s",ch+1);
        base1[0]=1;
        base2[0]=1;
        for(int i=1;i<=n;i++)
        {
            base1[i]=base1[i-1]*233%mod;
            base2[i]=base2[i-1]*2333%mod;
            h[i]=(h[i-1]*233+(ch[i]-96))%mod;
            g[i]=(g[i-1]*2333+(ch[i]-96))%mod;
        }
        for(int i=n/2;i>=1;i--)
        {
            f[i]=min(f[i+1]+2,(n-2*i)/2);
            while(f[i]&&(!check(i+1,n-f[i]+1-i,f[i])))
            {
                f[i]--;
            }
        }
        for(int i=1;i<=n/2;i++)
        {
            if(!check(1,n-i+1,i))
            {
                continue;
            }
            ans=max(ans,f[i]+i);
        }
        printf("%d",ans);
    }
  • 相关阅读:
    ckeditor+粘贴word
    java+批量下载大文件
    链接批量下载文件
    java+大文件上传解决方案
    php+提高大文件上传速度
    富文本粘贴word文档内容图片处理
    软件开发工具(三)——理论与开发过程
    c结构体里的数组与指针
    Java解析Property文件
    怎样高速编译mediatekoperator以下代码
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9637166.html
Copyright © 2011-2022 走看看