Description
Solution
枚举两字符串的开头,暴力往后扫大家应该会做吧,
设两字符串开头为
x,y(x<y)
,设
k=y−x
我们发现,如果对于多个位置,如果它在所在串的相对位置%k是相同的,那么这几个位都必须相同,
比如:两串的开头为1、3,k=2,那么,1、3、5、7等都必须相等,
换句话说,就是在两串相交时,会有一定的周期性,
(大家写两个数据看看就可以知道了)
发现开头没有必要一个个枚举,直接设前面开头为位置1,然后贪心找到合法的最右边,再弹掉开头即可,
复杂度: O(n2∗26)
Code
#include <cstdio>
#include <cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
const int N=3500;
int m,n,ans;
int a[N];
int b[N][28],bs[N];
int z[N],TI;
void UPD(int q)
{
int e=0;
fo(i,1,26)e=max(e,b[q][i]);
bs[q]=b[q][0]-e;
}
int main()
{
int q,w,e;
scanf("%d",&m);
char ch=' ';
for(;ch<'a'||ch>'z';ch=getchar());
for(;ch<='z'&&ch>='a';ch=getchar())a[++n]=ch-96;
ans=min(m,n);
fo(I,1,n)
{
fo(i,0,I)
{
bs[i]=0;
fo(j,0,26)b[i][j]=0;
}
q=0;TI++;
int S=1,T;
for(T=1;I+T<=n;T++)
{
w=T%I;
if(z[T]<TI)b[w][a[T]]++,b[w][0]++;
b[w][a[T+I]]++,b[w][0]++;
z[T]=z[T+I]=TI;
q-=bs[w];
UPD(w);
q+=bs[w];
for(;q>m;S++)
{
int t=S%I;
b[t][a[S]]--;
b[t][0]--;
q-=bs[t];
UPD(t);
q+=bs[t];
z[S]=0;
}
ans=max(ans,T-S+1);
}
}
printf("%d\n",ans);
return 0;
}