题意
- 在字符串S中找一个最短字串,使其包含26个字母
思路
- 暴力枚举
会T
- 双指针
:从头开始扫,更新右界直到扫全,然后更新左界直到缺字母,重复上述过程遍历整个串
AC代码
#include<bits/stdc++.h>
using namespace std;
int vis[26];
int main(){
string s;
cin>>s;
int slen=s.size();
int rst=1e7,cnt=0;
if(slen<27)cout<<-1<<endl;
else{
for(int l=0,r=0;l<slen;l++){
while(r<slen&&cnt<26)
{
if(vis[s[r]-'a']==0)cnt++;
vis[s[r]-'a']++;
r++;
}
if(cnt==26) rst=min(rst,r-l);
vis[s[l]-'a']--;
if(vis[s[l]-'a']==0)cnt--;
}
printf("%d\n",rst);
}
}
双指针的一些注意事项:
-
对于右界的更新问题:由于一般情况下只要进入了更新右界的循环就会给右边界加一,但是在满足条件时我们希望右边界不动,所以在更新右边界的循环里往往带着判定条件也就是本题的
cnt<26
和if(cnt==26) rst=min(rst,r-l)
-
这种对边界预处理的体现在丢手绢一题中体现更为明显
-
while(r<=n&&(sum+dis[r])*2<=ads)