楼上的 O ( n ) O(n) O(n)题解太强了,本菜鸡来说一说其他做法
这个题目看到的第一感觉就是二分答案,因为又是要求最小值且答案有单调性
设 n = ∣ S ∣ n=|S| n=∣S∣,二分最小的 k k k,然后 O ( n ) O(n) O(n)的扫出每个字串,把每个字串的字符信息保存,然后判断每一个字串是否有公共字符。
我们发现这样做有一些浪费时间,因为每个字串的字符信息是不会变的,于是我们可以把它前缀和记录一下
s u m [ i ] [ j ] sum[i][j] sum[i][j]表示前i个字符字符j出现的次数,然后枚举字串起点 l l l和终点 r r r,每个字符出现的次数就是 s u m [ r ] [ j ] − s u m [ l − 1 ] [ j ] sum[r][j]-sum[l-1][j] sum[r][j]−sum[l−1][j]就好了
优化完的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
w o w ! wow! wow!
n n n才 1 0 5 10^5 105这。。。二分也能过,出题人tql
#include <map>
#include <set>
#include <ctime>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <bitset>
#include <cstdio>
#include <cctype>
#include <string>
#include <cstring>
#include <cassert>
#include <climits>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std ;
#define rep(i, a, b) for (int (i) = (a); (i) <= (b); (i)++)
#define per(i, a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define clr(a) memset(a, 0, sizeof(a))
#define ass(a, sum) memset(a, sum, sizeof(a))
#define lowbit(x) (x & -x)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define enter cout << endl
#define siz(x) ((int)x.size())
typedef long long ll ;
typedef unsigned long long ull ;
typedef vector <int> vi ;
typedef pair <int, int> pii ;
typedef map <int, int> mii ;
typedef map <string, int> msi ;
const int N = 100010 ;
const int M = 30 ;
const int INF = 0x3f3f3f3f ;
const int iinf = 1 << 30 ;
const ll linf = 2e18 ;
const int MOD = 1000000007 ;
void print(int x) { cout << x << endl ; exit(0) ; }
void PRINT(string x) { cout << x << endl ; exit(0) ; }
void douout(double x){ printf("%lf\n", x + 0.0000000001) ; }
int a[M], b[M] ;
int sum[N][M] ;
char s[N] ;
int n ;
bool check(int x) {
for (int i = 1; i <= 26; i++) b[i] = iinf ;
for (int r = x; r <= n; r++) {
int l = r - x + 1 ;
for (int i = 1; i <= 26; i++) a[i] = sum[r][i] - sum[l - 1][i] ;
for (int i = 1; i <= 26; i++) b[i] = min(b[i], a[i]) ;
}
for (int i = 1; i <= 26; i++) if (b[i]) return true ;
return false ;
}
signed main(){
scanf("%s", s + 1) ; n = strlen(s + 1) ;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 26; j++) sum[i][j] = sum[i - 1][j] ;
sum[i][s[i] - 'a' + 1]++ ;
}
int l = 0, r = n + 1 ;
while (l + 1 < r) {
int mid = (l + r) >> 1 ;
if (check(mid)) r = mid ;
else l = mid ;
}
printf("%d\n", r) ;
return 0 ;
}