G- eli和字符串
题目描述:
eli拿到了一个仅由小写字母组成的字符串。
她想截取一段连续子串,这个子串包含至少 个相同的某个字母。
她想知道,子串的长度最小值是多少?
注:所谓连续子串,指字符串删除头部和尾部的部分字符(也可以不删除)剩下的字符串。例如:对于字符串"arcaea”而言,“arc”、“rcae”都是其子串。而“car”、“aa”则不是它的子串。
解法:比赛时想记录每个字符对应下标然后从头到尾两层循环一遍的,提交超时了,赛后就看了看大佬的做法,用队列来做,因为队列可以先进先出。这里学到了以后设定int型的最大值时用0x3f3f3f3f好
#include<iostream>
#include<queue>
#include<cstdio>
#include<string>
using namespace std;
queue<int>a[30];
int last[30]={0},ans=0x3f3f3f3f,n,k;
int main()
{
string s;
scanf("%d%d",&n,&k);
cin>>s;
for(int i=0;i<s.length();i++)
{
int id=s[i]-'a';//id用于记录对应字母在字母表中的顺序-1
last[id]=i;
a[id].push(i);
if(a[id].size()>=k)//一满足不小于K了就会进入循环,所以last[id]用来记录最近出现的字母在字符串的位置
{
ans=min(ans,last[id]-a[id].front());
a[id].pop();
}
}
if(ans==0x3f3f3f3f)
ans=-1;
else//由于减完后字母对应的Id比正常少1,这里加上,比如a:1,代码减完是:0
ans++;
printf("%d",ans);
}
H-nozomi和字符串
题目要求及数据:
解法:贪心的想一想操作一定是对连续的0或者1进行操作的,否则不是最优解。比如101010,若操作次数k=2,那么必然是将第一个0和第二个0翻转变成1,得到111110;而不是将第一个0和第三个0变成1,得到111011,操作要么全变0要么全变1,两种情况都写一下,注意的是端点要赋个值
代码:
#include<bits/stdc++.h>
using namespace std;
string s;
vector<int>v0,v1; //v0存字符'0'的坐标位置,v1存字符'1'的坐标位置
int main(){
int n,k,i,j;
cin>>n>>k;
cin>>s;
v0.push_back(-1);
v1.push_back(-1);
for(i=0;i<n;i++){
if(s[i]=='0')v0.push_back(i);
else v1.push_back(i);
}
v0.push_back(n);
v1.push_back(n);
int ma=0;
if(v0.size()-2<=k)ma=n;//减2是因为上面自己加了个-1、n,目的是为了让下面的[j+1]、[i-1]有对应的值
else{
for(i=1,j=k;j<v0.size()-1;i++,j++){
ma=max(ma,v0[j+1]-v0[i-1]-1);//第i个0到第j个0改变为1之后,连续相同字符的子串最大长度应当为第j+1个0所在的位置减去第i-1个0所在的位置减1
}
}
if(v1.size()-2<=k)ma=n;
else{
for(i=1,j=k;j<v1.size()-1;i++,j++){
ma=max(ma,v1[j+1]-v1[i-1]-1);
}
}
cout<<ma;
}