Description
Input
Output
Sample Input
2
tmirkoxlyzmirkoslav
Sample Output
8
Data Constraint
赛时
比赛时想到一个
O
(
n
3
)
O(n^3)
O(n3)的东东,就是枚举起点,然后暴力向右走。
结果发现可以重合。然后再化化图发现,后面的部分是呈周期性呈现的。
具体一点就是假设两个起点之间的距离为L,那么满足答案的序列就是每个长度为L的区间是完全相等的。
这有什么好处呢?现在我们判断是否满足题目要求就变成了每L个位置的点是否都相同。
我们就弄一个数组
p
[
i
]
[
0
−
25
]
p[i][0-25]
p[i][0−25]来记录每个位置的各个字母出现的次数。
于是枚举就可以
O
(
n
3
∗
26
)
O(n^3*26)
O(n3∗26)的复杂度来做了。如果同时维护一个最大值,则可以省去里面的26。变成纯粹的
O
(
n
3
)
O(n^3)
O(n3)
题解
其实只差一步!
我们发现,改变一下枚举起点的方式就可以了。
先枚举L的大小。然后用两个指针来维护,如果当前序列可行那么就把后面指针往后挪,否则就把前面指针往后挪。
在维护一下最大值,即可做到
O
(
n
2
∗
26
)
O(n^2*26)
O(n2∗26)
代码
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int n,m,a[3100],p[3100][26],ma[3100],gs[3100];
char s[3100];
int main()
{
// freopen("data.in","r",stdin);
freopen("repeat.in","r",stdin);
freopen("repeat.out","w",stdout);
scanf("%d",&m);
scanf("%s",s+1);
n=strlen(s+1);
for (int i=1;i<=n;i++)
{
a[i]=s[i]-'a';
}
int ans=0;
for (int i=1;i<=n;i++)
{
if (i==9)
{
int j=0;
}
int tot=0;
for (int k=0;k<i;k++)
{
for (int c=0;c<=25;c++) p[k][c]=0;
ma[k]=0;
}
int head=1;int tail=1;int op=1+i;
while (tail+i<=n)
{
int o=tail%i;
if (tail<=head+i-1)
{
p[o][a[tail]]++;
if (ma[o]>=p[o][a[tail]]) tot++;
else ma[o]=p[o][a[tail]];
}
p[o][a[tail+i]]++;
if (ma[o]>=p[o][a[tail+i]]) tot++;
else ma[o]=p[o][a[tail+i]];
if (tot<=m) ans=max(ans,tail-head+1);
while (tot>m)
{
int u=head%i;
if (tail<=head+i-1)
{
p[u][a[head+i]]--;
int zd=0;
for (int g=0;g<=25;g++) zd=max(zd,p[u][g]);
if (zd!=ma[u]) ma[u]=zd; else tot--;
}
p[u][a[head]]--;
int zd=0;
for (int g=0;g<=25;g++) zd=max(zd,p[u][g]);
if (zd!=ma[u]) ma[u]=zd; else tot--;
head++;
}
tail++;
}
}
printf("%d\n",ans);
}