k-substrings Codeforces - 961F

不会做。。

官方题解:

1.枚举某个前缀(指题目要求的相同前后缀中的前缀)的中心位置i,那么对应后缀的中心位置已经确定了(n-i+1),可以二分答案求出对于每个中心位置i最大的符合要求的相同前后缀(设长度为2x+1),然后更新ans[i-x]为2x+1;最后把每个ans[i]用ans[i-1]-2尝试更新一下

2.其实以上做法也基于这个结论?

ans[i-1]<=ans[i]+2,这个可以容易地用反证法证明(类似kmp)

因此从ans[(n+1)/2]开始求就行了

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 namespace Hash
 5 {
 6 typedef unsigned long long ULL;
 7 const int md2=999999937;
 8 struct Hdata
 9 {
10     ULL d1;int d2;
11     Hdata(ULL a,int b):d1(a),d2(b<md2?(b<0?b+md2:b):b-md2){}
12     Hdata():d1(0),d2(0){}
13 };
14 Hdata operator*(const Hdata &a,int b)    {return Hdata(a.d1*b,ULL(a.d2)*b%md2);}
15 Hdata operator*(const Hdata &a,const Hdata &b)    {return Hdata(a.d1*b.d1,ULL(a.d2)*b.d2%md2);}
16 Hdata operator+(const Hdata &a,int b)    {return Hdata(a.d1+b,a.d2+b);}
17 Hdata operator-(const Hdata &a,const Hdata &b)    {return Hdata(a.d1-b.d1,a.d2-b.d2);}
18 bool operator==(const Hdata &a,const Hdata &b)    {return a.d1==b.d1&&a.d2==b.d2;}
19 }
20 using Hash::Hdata;
21 char s[1000100];
22 Hdata hs[1000100];
23 const int X=131;
24 Hdata pwx[1000100];
25 Hdata ghash(int l,int r)
26 {
27     if(l>r)    return Hdata(0,0);
28     return hs[r]-hs[l-1]*pwx[r-l+1];
29 }
30 int n,ans[1000100],l;
31 bool issame(int l1,int r1,int l2,int r2)
32 {
33     if(l1<1||l1>n||r1<1||r1>n||l2<1||l2>n||r2<1||r2>n)    return 0;
34     return ghash(l1,r1)==ghash(l2,r2);
35 }
36 int main()
37 {
38     int i,j;
39     scanf("%d%s",&n,s+1);
40     for(i=1;i<=n;i++)    hs[i]=hs[i-1]*X+s[i];
41     pwx[0]=Hdata(1,1);
42     for(i=1;i<=n;i++)    pwx[i]=pwx[i-1]*X;
43     l=(n+1)/2;
44     if(n%2==1)    ans[l]=-1;
45     else    ans[l]=s[l]==s[l+1]?1:-1;
46     for(i=l-1;i>=1;i--)
47     {
48         for(j=ans[i+1]+2;j!=-1&&!issame(i,i+j-1,n-i-j+2,n-i+1);j-=2);
49         ans[i]=j;
50     }
51     for(i=1;i<=l;i++)    printf("%d ",ans[i]);
52     return 0;
53 }

猜你喜欢

转载自www.cnblogs.com/hehe54321/p/9022860.html