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 }

浙公网安备 33010602011771号