• [BZOJ2803][Poi2012]Prefixuffix


    2803: [Poi2012]Prefixuffix

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 219  Solved: 95
    [Submit][Status][Discuss]

    Description


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

    Input

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

    Output

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

    Sample Input

    15
    ababbabababbaab

    Sample Output

    6

    HINT

     

    Source

    [Submit][Status][Discuss]


    这题好厉害啊!!!

    设$f[i]=[i+1,n-i]$这个子串中前缀和后缀最长的一样的。

    这样答案就=$max{f[i]+i},其中[1,i]=[n-i+1,n]$

    发现一个性质$f[i-1]<=f[i]+2$,这样就可以类似一个单调栈来$O(n)$处理了。

    (PS:POI卡hash,太差了!!)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define N 1000010
     4 #define ll long long
     5 int pow[N][2],hash[N][2],mod[2]={99824435,1004535809},n,ans;
     6 char s[N];
     7 inline int gethash(int x,int l,int r)
     8 {return (hash[r][x]-(ll)hash[l-1][x]*pow[r-l+1][x]%mod[x]+mod[x])%mod[x];}
     9 inline bool check(int l,int r,int x)
    10 {
    11     return gethash(0,l,l+x-1)==gethash(0,r-x+1,r)&&gethash(1,l,l+x-1)==gethash(1,r-x+1,r);
    12 }
    13 int main()
    14 {
    15     scanf("%d
    ",&n);
    16     pow[0][0]=pow[0][1]=1;
    17     for(int i=1;i<=n;i++)
    18     {
    19         s[i]=getchar();
    20         for(int x=0;x<=1;x++)
    21         hash[i][x]=((ll)hash[i-1][x]*233+s[i])%mod[x],
    22         pow[i][x]=(ll)pow[i-1][x]*233%mod[x];
    23     }
    24     for(int i=n/2,j=0;i;i--,j=std::min(j+2,n/2-i))
    25     if(check(1,n,i))
    26     for(;~j;j--)
    27     if(check(i+1,n-i,j))
    28     {
    29         ans=std::max(ans,i+j);
    30         break;
    31     }
    32     printf("%d",ans);
    33 }
    View Code
  • 相关阅读:
    前端开发之初探五
    前端开发之初探四
    前端开发之初探三
    漫谈
    前端工程师的发展之路
    SVG
    前端开发之初探一
    前端开发之初探二
    详解浏览器缓存
    webStroage案例
  • 原文地址:https://www.cnblogs.com/xuruifan/p/5193135.html
Copyright © 2020-2023  润新知