传送门
题解:
用队列算一下每个位置向后找到哪里有 k k k 个指定字符,然后枚举开头 O ( 1 ) O(1) O(1) 跳到结尾即可算出中间要删掉多少。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int N=2e5+7;
int n,K;
char s[N];
int nxJ[N],nxO[N],nxI[N];
void get(int nx[],char c){
std::queue<int>q;int l=0;
for(int re i=1;i<=n;++i)
if(s[i]==c){
q.push(i);
if(q.size()==K){
for(int re j=l+1;j<=q.front();++j)
nx[j]=i;
l=q.front();q.pop();
}
}
for(int re i=l+1;i<=n;++i)nx[i]=1e9;
}
void Main(){
scanf("%d%d%s",&n,&K,s+1);int ans=1e9;
get(nxJ,'J'),get(nxO,'O');get(nxI,'I');
for(int re i=1;i<=n;++i){
int j=nxJ[i];if(j>=n)continue;
j=nxO[j+1];if(j>=n)continue;
j=nxI[j+1];if(j>n)continue;
ans=std::min(ans,j-i+1-K*3);
}cout<<(ans==1e9?-1:ans)<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("JJOOII.in","r",stdin);
#endif
}
signed main(){file();Main();}