题目链接(密码 hpuacm2018):https://vjudge.net/contest/241732#overview
二分参考之前的博客:https://blog.csdn.net/hpu2022/article/details/79845630
尺取:
理解了尺取后用题目来做练习,实际问题中尺取的条件多种多样,要多做练习多总结。
训练题中的B题:
#include <bits/stdc++.h>
using namespace std;
char str[100000+10];
int vis[200];
int main()
{
int n;
set<char> s;
while( ~scanf("%d", &n ) )
{
int kind = 0; //num记录不同的元素出现的总个数
scanf("%s", str );
s.clear();
for( int i=0; i<n; i++ )
s.insert( str[i] );
kind = s.size();
memset( vis, 0, sizeof(vis) ); //先清0
int ans = int(1e9);
int left = 0; //记录起点,开始在 0
int cnt = 0;
for( int i=0; i<n; i++ )
{
if( !vis[str[i]] ) //cnt记录不同字母出现的次数,即cnt记录的是已经出现的种类
cnt ++;
vis[ str[i] ]++; //每个字母出现次数+1
if( cnt == kind )
{
while( cnt == kind )
{
ans = min( ans, i - left +1 );
if( vis[str[left]] == 1 ) // left 起点的类型,直到 i 终点也只出现一次,再向后移动cnt != kind,退出循环
cnt--;
vis[str[left]]--; //起点出现次数先-1,再右移
left++;
}
}
}
printf("%d\n", ans );
}
return 0;
}