CF961F k-substrings

CF961F k-substrings

题意:给出长度为nn的字符串T,对于每一个k子串,找出最大长度的t,使得t是k子串的前后缀,且t长度为奇数
思路:
从T串的中心开始向两边扩展。首先处理T串中心的k子串:如果T串长度为奇数,ans=-1;如果长度为偶数,ans=1或-1。
接着开始向两边扩展。下一个的最长前后缀长度最多是上一个的长度+2,最小是-1 。枚举每一种情况,用hash来判断是否能成立。
 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 const int N=1e6+7;
 5 const int P=107;
 6 const ll mod=1e9+7;
 7 int n;
 8 char s[N];
 9 int ans[N];
10 int cnt,l,r;
11 ll x,y;
12 ll p[N],h[N];
13 
14 void Hash(){
15     p[0]=1;
16     for(int i=1;i<=n;i++){
17         p[i]=p[i-1]*P%mod;
18         h[i]=(h[i-1]*P%mod+s[i]-'a'+1)%mod;
19     }
20 }
21 
22 ll hs(int l,int r){
23     return ((h[r]-h[l-1]*p[r-l+1]%mod+mod)+mod)%mod;
24 }
25 
26 int main(){
27     scanf("%d%s",&n,s+1);
28     Hash();
29     cnt=n+1>>1;
30     if(n&1)ans[cnt]=-1,l=r=cnt;
31     else{
32         l=n>>1,r=l+1;
33         if(s[l]==s[r])ans[cnt]=1;
34         else ans[cnt]=-1;
35     }
36     
37     for(int i=cnt-1;i>=1;i--){
38         l--,r++;
39         for(int j=ans[i+1]+2;j>=-1;j-=2){
40             x=hs(l,l+j-1),y=hs(r-j+1,r);
41             if(x==y || j==-1){
42                 ans[i]=j;
43                 break;
44             }
45         }
46     }
47     for(int i=1;i<=cnt;i++)
48         printf("%d ",ans[i]);
49     return 0;
50 }
View Code

 

posted @ 2020-03-15 17:54  Chillilly  阅读(181)  评论(0)    收藏  举报