链接:https://www.nowcoder.com/acm/contest/161/A
来源:牛客网
题目描述
小N现在有一个字符串S。他把这这个字符串的所有子串都挑了出来。一个S的子串T是合法的,当且仅当T中包含了所有的小写字母。小N希望知道所有的合法的S的子串中,长度最短是多少。
链接:https://www.nowcoder.com/acm/contest/161/A
来源:牛客网
输入描述:
一行一个字符串S。只包含小写字母。S的长度不超过106.
输出描述:
一行一个数字,代表最短长度。数据保证存在一个合法的S的子串。
示例1
输入
复制
ykjygvedtysvyymzfizzwkjamefxjnrnphqwnfhrnbhwjhqcgqnplodeestu
输出
复制
49
时间复杂度和空间复杂度,都是极佳的
1.一开始二分+暴力枚举 TLE,2.开始维护26个字符的树状数组,直接, MLE ,直接崩溃
应该是双指针,这种思想还是蛮普遍的,找到最右边的合法点,然后不断的缩。
#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;
}