39-子串-尺取法

链接:https://www.nowcoder.com/acm/contest/161/A
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

小N现在有一个字符串S。他把这这个字符串的所有子串都挑了出来。一个S的子串T是合法的,当且仅当T中包含了所有的小写字母。小N希望知道所有的合法的S的子串中,长度最短是多少。

输入描述:

一行一个字符串S。只包含小写字母。S的长度不超过10
6
.

输出描述:

一行一个数字,代表最短长度。数据保证存在一个合法的S的子串。
示例1

输入

复制
ykjygvedtysvyymzfizzwkjamefxjnrnphqwnfhrnbhwjhqcgqnplodeestu

输出

复制
49

思路:设置两个指针,左右放缩。
#include <iostream>
#include <cstring>
using namespace std;
int a[26];

int main(){
	string str;
	cin >> str;
	int len = str.length();
	int i = 0, j = 0, ct = 0, ans = 0x3f3f3f3f;
	while(i < len){
		if(a[str[i] - 'a'] == 0)
			ct++;
		a[str[i] - 'a']++;
		while(a[str[j] - 'a'] > 1){
			a[str[j] - 'a']--, j++;
		}
		if(ct == 26 && i - j + 1 < ans)
			ans = i - j + 1;
		i++;
	}
	cout << ans << endl;
	return 0;
} 

  下面这种没过,还不知道原因!!!

#include <iostream>
#include <cstring>
#include <map>
#include <set>
using namespace std;

int main(){
	string str;
	cin >> str;
	int left = 0, right = 0;
	map<char, int> mymap;
	set<char> myset;
	for(int i  = 0; i < 26; i++){
		mymap['a' + i] = 0;
	}
	int len = str.length(), minsize = 0x3f3f3f3f;
	int ct = 0;
	while(left < len && right < len + 1){
		if(myset.size() >= 26){
			mymap[str[left]]--;  //左边踢一个 
			if(mymap[str[left]] == 0){
				myset.erase(str[left]);
//				cout << str[left] << "--------------" << endl;
			}
			else{
				int r = right >= len ? len - 1 : right;
				if(minsize > r - left){
					minsize = r - left + 1 - 1; //踢掉了一个 
				}
			} 
			left++;
		}
		else{
			if(right >= len)
				break;
			if(myset.count(str[right]) == 0){
				ct++;
				myset.insert(str[right]);
				if(myset.size() >= 26 && minsize > right - left + 1){
					minsize = right - left + 1;
				}
			}
			mymap[str[right]]++;
			right++;		
		}
	}
	cout << minsize << endl;
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/zhumengdexiaobai/p/9569465.html