牛客挑戰賽23-A.字串(尺取)

大白QQly成長日記發表於2018-09-01

小N現在有一個字串S。他把這這個字串的所有子串都挑了出來。一個S的子串T是合法的,當且僅當T中包含了所有的小寫字母。小N希望知道所有的合法的S的子串中,長度最短是多少。

輸入描述:

一行一個字串S。只包含小寫字母。S的長度不超過106.

輸出描述:

一行一個數字,代表最短長度。資料保證存在一個合法的S的子串。

示例1

輸入

ykjygvedtysvyymzfizzwkjamefxjnrnphqwnfhrnbhwjhqcgqnplodeestu

輸出

49

思路:看了一眼題目,大致想了一下,沒有動手寫,大概是2個指標標記,一個在前標記種類,到達26種便停下,因為後面的就可以不要了。前面的指標,在遇到重複的字元時進行及時更新與前進。然後這個方法居然就是傳說中的尺取法........

程式碼如下:

#include<set>
#include<map>
#include<list>
#include<deque>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<stdio.h>
#include<sstream>
#include<stdlib.h>
#include<string.h>
//#include<ext/rope>
#include<iostream>
#include<algorithm>
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define per(i,a,b) for(int i=a;i<=b;++i)
#define max(a,b)  a>b?a:b
#define min(a,b)  a<b?a:b
#define LL long long 
#define swap(a,b) {int t=a;a=b;b=t} 
using namespace std;
//using namespace __gnu_cxx;
const int maxn=1e6+7;
int vis[26];
int n,s,k;
int main()
{
    string s1;
    cin>>s1;
    s=0x3f3f3f3f;
    int n=s1.size();
    per(i,1,n)
    {
        int t=s1[i-1]-'a';  
        if(vis[t]==0) k++;//注意,考慮第0個元素vis更新為0的情況
        vis[t]=i;
        if(k==26)
        {
            int z=0;
            per(j,0,25)
                z=max(z,i-vis[j]+1);        
            s=min(s,z);//不能直接跳出,需要迴圈完每一個子串
        }
    }
    cout<<s;
    return 0;
}