字串 (包含T全部元素的最小視窗)
阿新 • • 發佈:2019-01-05
題目描述
小N現在有一個字串S。他把這這個字串的所有子串都挑了出來。一個S的子串T是合法的,當且僅當T中包含了所有的小寫字母。小N希望知道所有的合法的S的子串中,長度最短是多少。
輸入描述:
一行一個字串S。只包含小寫字母。S的長度不超過106.
輸出描述:
一行一個數字,代表最短長度。資料保證存在一個合法的S的子串。
示例1
輸入
ykjygvedtysvyymzfizzwkjamefxjnrnphqwnfhrnbhwjhqcgqnplodeestu
輸出
49
時間複雜度和空間複雜度,都是極佳的
1.一開始二分+暴力列舉 TLE,2.開始維護26個字元的樹狀陣列,直接
應該是雙指標,這種思想還是蠻普遍的,找到最右邊的合法點,然後不斷的縮。
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<b;i++) const int N=1e6+10; char s[N]; int need_find[256],has_find[256]; int min_win(int slen) { rep(i,0,26)need_find[i+'a']++; int ans=slen; int res=0,tlen=26; for(int p1=0,p2=0;p2<slen;p2++){ if(!need_find[s[p2]])continue; has_find[s[p2]]++; if(has_find[s[p2]]<=need_find[s[p2]]) ++res; if(res==tlen){ while(p1<=p2&&has_find[s[p1]]>need_find[s[p1]]){ has_find[s[p1]]--; if(!has_find[s[p1]])--res; ++p1; } ans=min(ans,p2-p1+1); } } return ans; } int main() { scanf("%s",s); int len=strlen(s); int ans=min_win(len); printf("%d\n",ans); return 0; }