Description
小N现在有一个字符串S。他把这这个字符串的所有子串都挑了出来。一个S的子串T是合法的,当且仅当T中包含了所有的小写字母。小N希望知道所有的合法的S的子串中,长度最短是多少。
Solution
经典问题?一眼看出二分+尺取,先算出一共有多少种小写字母,然后再二分答案,显然字符串越长,越可能包含所有小写字母种类。
不过被搞了,这道题 strlen(s) 编译器没帮我优化emmmmm, 记得提前算出 len 吧。
Code
#pragma GCC optimize("O3") #include<bits/stdc++.h> using namespace std; typedef long long ll; const long long inf = 1e18; const int N = 1e6 + 5, mod = 998244353; int n; char s[N]; int vis[30] = {0}; int cnt, len; bool check(int x) { int mp[30] = {0}; int now = -1; for(int i = 0; i < len; i++) { while(now - i + 1 < x && now < len - 1) { now++; mp[s[now] - 'a']++; } int cur = 0; for(int j = 0; j < 26; j++) { cur += (mp[j] > 0); } if(cur == cnt) return true; mp[s[i] - 'a']--; } return false; } int main() { scanf("%s", s); len = strlen(s); for(int i = 0; i < len; i++) { vis[s[i] - 'a']++; } int ans = -1; cnt = 0; for(int i = 0; i < 26; i++) cnt += (vis[i] > 0); int left = 1, right = len; while(left <= right) { int mid = left + right >> 1; if(check(mid)) { ans = mid; right = mid - 1; } else { left = mid + 1; } } printf("%d\n", ans); return 0; }