G3. Good Substrings

http://codeforces.com/contest/316/problem/G3

利用RMQ 求 後綴的前綴在每個串裏面的個數

二分每個後綴滿足要求的最大和最小前綴長度

我用了十個後綴數組

代碼寫得有些拖沓

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long LL;
const int INF = 0x7f7f7f7f;
const int maxn = 111111;
const int mod = 1000000000;
const double eps = 1e-10;
char s[maxn];
char ss[12][maxn];
int A[20], B[20];
int Log[20];
int a[maxn], wa[maxn], wb[maxn], wv[maxn], wn[maxn];
int tp[maxn];
struct range_min_query {
    int i, j, k, r[18][maxn];
    void make(int n, int arr[]) {
        for (i = 0; i <= n; ++i)
            r[0][i] = arr[i];
        for (i = 0; i < 17; ++i) {
            k = Log[i];
            for (j = 0; j + k <= n; ++j)
                r[i + 1][j] = min(r[i][j], r[i][j + k]);
        }
    }
    int query(int L, int R) {
        if (R == L)
            return r[k][L];
        k = tp[R - L];
        return min(r[k][L], r[k][R - Log[k]]);
    }
} RMQ[10];
struct suffix_array {
    int sum[maxn], sa[maxn], rank[maxn], h[maxn];
    bool cmp(int r[], int a, int b, int l) {
        return (r[a] == r[b] && r[a + l] == r[b + l]);
    }
    void Da(int r[], int n, int m) {
        int i, j, p, *t;
        int *x = wa, *y = wb;
        for (i = 0; i < m; ++i)
            wn[i] = 0;
        for (i = 0; i < n; ++i)
            wn[x[i] = r[i]]++;
        for (i = 1; i < m; ++i)
            wn[i] += wn[i - 1];
        for (i = n - 1; i >= 0; --i)
            sa[--wn[x[i]]] = i;

        for (j = 1, p = 1; p < n; j <<= 1, m = p) {
            for (p = 0, i = n - j; i < n; ++i)
                y[p++] = i;
            for (i = 0; i < n; ++i)
                if (sa[i] >= j)
                    y[p++] = sa[i] - j;

            for (i = 0; i < n; ++i)
                wv[i] = x[y[i]];
            for (i = 0; i < m; ++i)
                wn[i] = 0;
            for (i = 0; i < n; ++i)
                wn[wv[i]]++;
            for (i = 1; i < m; ++i)
                wn[i] += wn[i - 1];
            for (i = n - 1; i >= 0; --i)
                sa[--wn[wv[i]]] = y[i];

            p = 1, t = x, x = y, y = t;
            for (x[sa[0]] = 0, i = 1; i < n; ++i)
                x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
        }
    }
    void Calheight(int r[], int n) {
        int i, j, k = 0;
        for (i = 1; i <= n; ++i)
            rank[sa[i]] = i;
        for (i = 0; i < n; h[rank[i++]] = k)
            for (k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; ++k)
                ;
    }
    int left(int l, int r, int k, range_min_query& RMQ) {
        int m, p = r, t, ans = r;
        while (l <= r) {
            m = (l + r) >> 1;
            t = RMQ.query(m + 1, p + 1);
            if (t >= k)
                ans = m, r = m - 1;
            else
                l = m + 1;
        }
        return ans;
    }
    int right(int l, int r, int k, range_min_query& RMQ) {
        int m, p = l, t, ans = l;
        while (l <= r) {
            m = (l + r) >> 1;
            t = RMQ.query(p + 1, m + 1);
            if (t >= k)
                ans = m, l = m + 1;
            else
                r = m - 1;
        }
        return ans;
    }
    int search(int p, int len, int k, range_min_query& RMQ) {
        int L, R;
        L = left(1, p, k, RMQ);
        R = right(p, len, k, RMQ);
        return getsum(L, R);
    }
    void Calsum(int n, int len) {
        sum[0] = 0;
        for (int i = 1; i <= n; ++i)
            sum[i] = sum[i - 1] + (sa[i] > len && sa[i] < n);
    }
    int getsum(int L, int R) {
        return sum[R] - sum[L - 1];
    }
} suffix[10], src;
int tlen[15];
bool low(int i, int n, int L) {
    int l, r, tmp;
    for (int k = 0; k < n; ++k) {
        l = suffix[k].rank[i];
        r = tlen[k];
        tmp = suffix[k].search(l, r, L, RMQ[k]);
        if (tmp > B[k])
            return false;
    }
    return true;
}
bool high(int i, int n, int L) {
    int l, r, tmp;
    for (int k = 0; k < n; ++k) {
        l = suffix[k].rank[i];
        r = tlen[k];
        tmp = suffix[k].search(l, r, L, RMQ[k]);
        if (tmp < A[k])
            return false;
    }
    return true;
}
int main() {
    int i, len, j;
    Log[0] = 1;
    for (i = 1; i < 20; ++i)
        Log[i] = Log[i - 1] << 1;
    tp[1] = 0;
    i = 0;
    for (j = 2; j < maxn; ++j) {
        if (Log[i + 1] < j)
            tp[j] = ++i;
        else
            tp[j] = i;
        //printf("%d %d\n",j,tp[j]);
    }
    scanf("%s", s);
    len = strlen(s);
    for (i = 0; i <= len; ++i)
        a[i] = (int) s[i];
    src.Da(a, len + 1, 128);
    src.Calheight(a, len);
    for (i = 0; i < 10; ++i)
        for (j = 0; j < len; ++j)
            ss[i][j] = s[j];
    int n;
    scanf("%d", &n);
    for (i = 0; i < n; ++i) {
        ss[i][len] = '$';
        scanf("%s%d%d", ss[i] + len + 1, A + i, B + i);
        tlen[i] = strlen(ss[i]);
        for (j = 0; j <= tlen[i]; ++j)
            a[j] = (int) ss[i][j];
        suffix[i].Da(a, tlen[i] + 1, 128);
        suffix[i].Calheight(a, tlen[i]);
        suffix[i].Calsum(tlen[i], len);
        RMQ[i].make(tlen[i] + 1, suffix[i].h);
    }
    int L, R, p, m, l, r;
    int ans = 0;
    for (i = 0; i < len; ++i) {
        p = src.rank[i];
        L = src.h[p] + 1;
        R = len - i;
        l = -1, r = -2;
        while (L <= R) {
            m = (L + R) >> 1;
            if (low(i, n, m))
                l = m, R = m - 1;
            else
                L = m + 1;
        }

        L = src.h[p] + 1;
        R = len - i;
        while (L <= R) {
            m = (L + R) >> 1;
            if (high(i, n, m))
                r = m, L = m + 1;
            else
                R = m - 1;
        }
        if (r != -2 && l != -1 && r >= l)
            ans += (r - l + 1);
    }
    printf("%d\n", ans);
    return 0;
}



發佈了102 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章