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 }