Description
Solution
如果两个串重叠的话,那么很明显这个串会是一个周期串(画个图就知道了)。
枚举两个串的左端点的间距k,那么根据周期串的性质,在%k相同的地方都是相同的,那么我们枚举k,然后在枚举第一个串的左端点,然后用一个指针j向右扫过去。如果要把%k相同的修改为相同的话,那么就是保留其中出现次数最多的字符。那么我们对于%k的位置要存储每个字符出现多少次还有出现最多的是什么,和出现次数为p的个数,这个可以方便修改,当i向右移的时候,假如最大值的个数变为了0,那么最大值也最多向左移一位。每次j都一道不能再移为止。
最后j-i+1-k就是答案
Code
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=3007;
int i,j,k,l,t,n,m,ans,p,kk;
char s[maxn];
int a[maxn],d[220][maxn],b[maxn],c[maxn],o,g[maxn][maxn];
int main(){
freopen("repeat.in","r",stdin);
freopen("repeat.out","w",stdout);
scanf("%d",&kk);
scanf("%s",s+1);n=strlen(s+1);fo(i,1,n)a[i]=s[i]-'a';
fo(k,1,n){
j=k-1;o=0;fo(i,1,j)g[i][0]++;
fo(i,1,j){
t=++d[a[i]][i];g[i][t]++;g[i][t-1]--;
if(t>c[i])c[i]=t;else o++;
}
fo(i,1,n-k){
while(j+1<=n){
if(d[a[j+1]][(j+1)%k]+1<=c[(j+1)%k]&&o+1>kk)break;
j++;t=++d[a[j]][j%k];g[j%k][t]++;g[j%k][t-1]--;
if(t>c[j%k])c[j%k]=t;
else o++;
}
t=--d[a[i]][i%k];g[i%k][t]++,g[i%k][t+1]--;
if(!g[i%k][c[i%k]])c[i%k]--;else o--;
ans=max(ans,j-i+1-k);
}
fo(i,1,j){
g[i%k][d[a[i]][i%k]]=0;
d[a[i]][i%k]=0;
c[i%k]=0;
}
// memset(d,0,sizeof(d));memset(g,0,sizeof(g));memset(c,0,sizeof(c));
}
printf("%d\n",ans);
}