尺取法的应用

They Are Everywhere ## 他们到处都是


Sergei B., the young coach of Pokemons, has found the big house which consists of n flats ordered in a row from left to right. It is possible to enter each flat from the street. It is possible to go out from each flat. Also, each flat is connected with the flat to the left and the flat to the right. Flat number 1 is only connected with the flat number 2 and the flat number n is only connected with the flat number n - 1.
There is exactly one Pokemon of some type in each of these flats. Sergei B. asked residents of the house to let him enter their flats in order to catch Pokemons. After consulting the residents of the house decided to let Sergei B. enter one flat from the street, visit several flats and then go out from some flat. But they won’t let him visit the same flat more than once.
Sergei B. was very pleased, and now he wants to visit as few flats as possible in order to collect Pokemons of all types that appear in this house. Your task is to help him and determine this minimum number of flats he has to visit.
谢尔盖·B。这所大房子由从左到右排列着的n套公寓组成。从街上每一套公寓都可以进去。从每个公寓出去都是可能的。此外,每一套公寓都与左边的公寓和右边的公寓相连。平面1只与平面2相连,平面n只与平面n - 1相连。
每套公寓里都有一只口袋妖怪。谢尔盖·B.要求居民们让他进入他们的公寓,以便抓到口袋妖怪。在征询了居民的意见后,他们决定让谢尔盖B.从街上进入一套公寓,参观几套公寓,然后从一套公寓出去。但他们不会让他再去同一套公寓一次。
谢尔盖·B.很高兴,现在他想尽量少去看看公寓,这样就能收集到这个房子里出现的各种类型的口袋妖怪。你的任务是帮助他确定他必须参观的最小数量的公寓。


Input
The first line contains the integer n (1 ≤ n ≤ 100 000) — the number of flats in the house.
The second line contains the row s with the length n, it consists of uppercase and lowercase letters of English alphabet, the i-th letter equals the type of Pokemon, which is in the flat number i.
第一行包含整数n≤n≤100(000)-公寓房子里的数量。
第二行包含长度为n的行s,由英文字母的大写字母和小写字母组成,第i个字母等于口袋妖怪的类型,在单位号i中。

Output
Print the minimum number of flats which Sergei B. should visit in order to catch Pokemons of all types which there are in the house.
打印出谢尔盖。B.应该参观的最小数量的公寓,这样可以抓住家里所有类型的口袋妖怪。

Examples
Input
3
AaA
Output
2
Input
7
bcAAcbc
Output
3
Input
6
aaBCCe
Output
5
Note
In the first test Sergei B. can begin, for example, from the flat number 1 and end in the flat number 2. A a
In the second test Sergei B. can begin, for example, from the flat number 4 and end in the flat number 6. A c b
In the third test Sergei B. must begin from the flat number 2 and end in the flat number 6. a B C C e


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100100
char str[maxn];
int big[30];//分别记录某种大写字母出现的个数 
int lit[30];//分别记录某种小写字母出现的个数 
int main()
{
    int n,i,a,j;
    while(scanf("%d",&n)!=EOF)
    {
        memset(big,0,sizeof(big));
        memset(lit,0,sizeof(lit));
        scanf("%s",str);
        int sum=0;      //表示字符串中所有字符的种类数 
        for(i=0;i<n;++i)
        {
            if('a'<=str[i]&&str[i]<='z')//统计字符串中一共有多少种字符 
            {
                a=str[i]-'a';   
                if(!lit[a])     //若没有出现
                {
                    sum++;  //种类数加一
                    lit[a]=1;//下次不再记数同样的 
                }
            }
            else
            {
                a=str[i]-'A';
                if(!big[a])
                {
                    sum++;
                    big[a]=1;
                }
            }
        }
        int cnt=0;      //子串中所含的字符种类数 
        int start=0,ans=n;
        memset(big,0,sizeof(big));
        memset(lit,0,sizeof(lit));
        for(i=0;i<n;++i)
        {
            if('a'<=str[i]&&str[i]<='z')
            {
                a=str[i]-'a';
                if(!lit[a])     //若没有这个种类 
                    cnt++;   //种类数+1; 
                lit[a]++;   //此种类记入次数 
            }
            if('A'<=str[i]&&str[i]<='Z')
            {
                a=str[i]-'A';
                if(!big[a])
                    cnt++;
                big[a]++;
            }
            if(cnt==sum)//子串包含所有字符种类时,子串首部往后移动,并记录最短的满足条件的子串长度 
            {
                while(cnt==sum)
                {
                    if(i-start+1<ans)   //ans=n,最右端 ,表示满足题意的右端点值 
                        ans=i-start+1;      //(尺取)更新ans ,推进右端点
                    if('a'<=str[start]&&str[start]<='z')
                    {
                        a=str[start]-'a';   
                        lit[a]--;   
                        if(!lit[a])     //如果就出现了一次,那么左端点推进后就不再包含这个字母,
                            cnt--;      //此时不满足题意,更改cnt的值使cnt==sum的条件不满足,结束while循环  
                    }
                    if('A'<=str[start]&&str[start]<='Z')
                    {
                        a=str[start]-'A';
                        big[a]--;
                        if(!big[a])
                            cnt--;
                    }
                    start++;        //左端点推进 
                }
            }
        } 
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/shf1730797676/article/details/81267675