1. 程式人生 > >CF888C K-Dominant Character 題解

CF888C K-Dominant Character 題解

樓上的 O ( n ) O(n) 題解太強了,本菜雞來說一說其他做法

這個題目看到的第一感覺就是二分答案,因為又是要求最小值且答案有單調性

n

= S n=|S| ,二分最小的 k k ,然後 O
( n ) O(n)
的掃出每個字串,把每個字串的字元資訊儲存,然後判斷每一個字串是否有公共字元。

我們發現這樣做有一些浪費時間,因為每個字串的字元資訊是不會變的,於是我們可以把它字首和記錄一下

s u

m [ i ] [ j ] sum[i][j] 表示前i個字元字元j出現的次數,然後列舉字串起點 l l 和終點 r r ,每個字元出現的次數就是 s u m [ r ] [ j ] s u m [ l 1 ] [ j ] sum[r][j]-sum[l-1][j] 就好了

優化完的時間複雜度為 O ( n l o g n ) O(nlogn)

w o w ! wow!

n n 1 0 5 10^5 這。。。二分也能過,出題人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 ;
}