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)。

原文地址:https://www.cnblogs.com/Scx117/p/8727909.html