• CF961F k-substring


    题意:给你一个字符串(sl<=1e6),问每一个起点到1和终点到sl距离相等的子串的最长不等于串长的border。

    标程:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 const int can=31;
     7 const int mod=20030321;
     8 const int N=1000005;
     9 int ha[N],pow[N],n,ans[N],l,r,len,cnt;
    10 char s[N];
    11 int S(int x,int l)
    12 {return ((ll)ha[x+l-1]-(ll)ha[x-1]*pow[l]%mod+mod)%mod;}
    13 int main()
    14 {
    15     scanf("%d%s",&n,s+1);
    16    pow[0]=1;
    17    for (int i=1;i<=n;i++) pow[i]=(ll)pow[i-1]*can%mod;
    18    for (int i=1;i<=n;i++) ha[i]=((ll)ha[i-1]*can%mod+(s[i]-'a'+1))%mod;
    19    if (n&1) l=r=n/2+1;else l=n/2,r=l+1;len=1;
    20    while (r<=n)
    21    {
    22        while (len!=-1&&S(l,len)!=S(r-len+1,len)||len>=r-l+1) len-=2;
    23       ans[++cnt]=len;
    24        l--,r++;    len+=2;
    25     }
    26     for (int i=cnt;i>=1;i--) printf("%d ",ans[i]);
    27    return 0;
    28 }

    题解:hash+单调性

    对于每一个串二分+hash?这样的答案并没有单调性。

    但是(分析数据)经过有理有据的推导,发现所有这样的串的答案是具有单调性的。

    对于一个串,如果在它的两边各加一个字符,那么它的border长度最多+2。

    证明:

    比如现在完成一个串A....B(A,B都是字符块,并且为该串的最长border

    左右各扩展:xA....By

    可以证明最优情况下的匹配是xAz...gBy,不会出现xAC...DBy(C,D是长度>1的字符块)

    如果存在xAC=DBy.那么提取C的最后一个字母=y,D的第一个字母=x,即xACy=xDBy。

    所以AC=DB,不满足A,B是最长border。

    然后就直接hash比较即可。

    时间复杂度O(n)。

  • 相关阅读:
    spring 心跳更新
    eclipse 控制台输出太多,显示不完整
    String
    iOS 开发之如何生成SDK(2)-----生成framework
    如何防止自己的APP被Hook
    JavaAPI类
    Java面向对象三大特性—封装
    Java类与对象
    Java基础易错点1
    Java数组反转及二维数组
  • 原文地址:https://www.cnblogs.com/Scx117/p/8727909.html
Copyright © 2020-2023  润新知