zoukankan      html  css  js  c++  java
  • Codeforces961F. k-substrings

    $n leq 1000000$的字符串,对每一个子串$i$~$n-i+1$,求他最长的一个既是前缀又是后缀的子串。

    这题要求的东西具有“对称性”,不充分利用难以解决。这里的“对称性”不仅指询问是对称的,更指要求的那个公共部分是对称的——不对称的相同的子串对答案没有丝毫贡献。

    从贡献的角度入手,就是求每个前缀$i$和后缀$n-i+1$的一个在前缀$i$的末尾的、在后缀$n-i+1$的开头的一个最长公共串。嗯那赶紧二分+哈希。额等等,从$i$向前延伸,从$n-i+1$向后延伸,字符串是否相同,这样一个函数不单调哦。但是,如果您从前缀$i$的中点处和后缀$n-i+1$的中点处向两边分别延伸,这样字符串是否相同就是一个单调函数了。

    因此转移战线,枚举对称相同串的中间位置$i$,然后$i$和$n-i+1$分别向两边延伸看最长的相同串多长,用二分+哈希判断。假设这次二分的答案是$2x-1$,那么$ans_{i-x+1}$就会$max$上$2x-1$。但这个串对$i-x+1$到$i$处的答案都是有贡献的,并且贡献每次减2,为了体现这一点只需要最后统计答案时$ans_i =max(ans_i,ans_{i-1}-2)$即可。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 //#include<queue>
     5 //#include<vector>
     6 #include<algorithm>
     7 //#include<iostream>
     8 //#include<assert.h>
     9 using namespace std;
    10 
    11 int n;
    12 #define maxn 2000011
    13 char s[maxn];
    14 
    15 int h1[maxn],h2[maxn],p1[maxn],p2[maxn],mod1=998244353,mod2=1000000007;
    16 int geth1(int L,int R) {return (h1[R]-h1[L-1]*1ll*p1[R-L+1]%mod1+mod1)%mod1;}
    17 int geth2(int L,int R) {return (h2[R]-h2[L-1]*1ll*p2[R-L+1]%mod2+mod2)%mod2;}
    18 
    19 int ans[maxn];
    20 int main()
    21 {
    22     scanf("%d%s",&n,s+1);
    23     h1[0]=h2[0]=0;
    24     for (int i=1;i<=n;i++) h1[i]=(h1[i-1]*27ll+s[i]-'a'+1)%mod1,h2[i]=(h2[i-1]*27ll+s[i]-'a'+1)%mod2;
    25     p1[0]=p2[0]=1;
    26     for (int i=1;i<=n;i++) p1[i]=p1[i-1]*27ll%mod1,p2[i]=p2[i-1]*27ll%mod2;
    27     
    28     for (int i=0;i<=(n+1)>>1;i++) ans[i]=-1;
    29     for (int i=1;i<=n>>1;i++)
    30     {
    31         int L=0,R=i,p=n-i+1;
    32         while (L<R)
    33         {
    34             int mid=(L+R+1)>>1,a=i-mid+1,b=i+mid-1,c=p-mid+1,d=p+mid-1;
    35             if (geth1(a,b)==geth1(c,d) && geth2(a,b)==geth2(c,d)) L=mid;
    36             else R=mid-1;
    37         }
    38         ans[i-L+1]=max(ans[i-L+1],2*L-1);
    39     }
    40     for (int i=1;i<=(n+1)>>1;i++)
    41     {
    42         ans[i]=max(ans[i],ans[i-1]-2);
    43         printf("%d ",ans[i]);
    44     }
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    20180827 360笔试客观题
    20180821 hikvision笔试
    20180820 美团一面
    20180811 网易
    20180811 多益网络
    20180810 多益网络模拟笔试
    hbase --知识点总结
    flume知识点总结
    oracle --hint总结
    查看oracle的执行计划
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8728143.html
Copyright © 2011-2022 走看看