题意

  • 在字符串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<26if(cnt==26) rst=min(rst,r-l)

  • 这种对边界预处理的体现在丢手绢一题中体现更为明显

  •   while(r<=n&&(sum+dis[r])*2<=ads)