尺取法-最短的包含字符串

给出一个字符串,求该字符串的一个子串S,S包含A-Z中的全部字母,并且S是所有符合条件的子串中最短的,输出S的长度。如果给出的字符串中并不包括A-Z中的全部字母,则输出No Solution。

Input:

第1行1个字符串。字符串的长度 <= 100000。

Output:

输出包含A-Z的最短子串长度。如果没有符合条件的子串,则输出No Solution。 

示例:

Input1:

BVCABCDEFFGHIJKLMMNOPQRSTUVWXZYZZ

Output1:

28

Input2:

QQWERTYUIOPASDFGHJKLZXCVBNM

Output2:

26

思想:基本尺取法(滑动窗口),

整个过程分为4步:

1.初始化左右端

2. 右端不断向前滑动,直至满足条件

3.如果第二步无法满足条件,则终止,否则更新结果

4.左端扩大1,继续第二步

适用:在一个序列中,求满足条件连续子序列的最值(最小区间,或最大区间)

代码如下:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int nums[26];             //用于标记 A~Z 出现的次数
    string s;
    cin>>s;
    char cur;
    int L = 0,R = 0;          //初始化 左右端
    int cnt = 0;              //当前出现字母的种类
    int ans = 1e6;
    memset(nums,0,sizeof(nums));
    int len = s.size();
    while(R<len||cnt>=26)      // cnt>=26 防止出现最后一个 刚好满足26种字母后 左端无法滑动.
    {
        while(R<len && cnt !=26) //右端一直滑动到满足条件
        {
            cur = s[R++];
            if(nums[cur - 'A'] == 0)
            {
                nums[cur - 'A'] = 1;
                cnt++;
            }
            else
            {
                nums[cur - 'A']++;
            }
        }
        if(cnt==26) // 满足A~Z 左端滑动
        {
            ans = min(ans,R-L);
            cur = s[L++] ;
            nums[cur - 'A']--;
            if(nums[cur - 'A'] == 0) 
                cnt--;
        }

    }
    if(ans == 1e6)
        cout<<"No Solution"<<endl;
    else
        cout<<ans<<endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/PyhonLong/article/details/81541806