zoukankan      html  css  js  c++  java
  • 洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)

    题意

    题目链接

    Sol

    这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧

    但知道这题能用后缀数组做之后应该就不是那么难了

    首先把(S)(S0)拼到一起跑,求出Height数组

    暴力枚举每个后缀是否能成为答案。

    具体来说,每次比较当前后缀和(S_0)的lcp,如果长度(< N)的话就从不合法的位置继续匹配

    rmq维护一下区间lcp最小值

    BZOJ上被完美卡常

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 2e5 + 10;
    const int INF = 2333;
    inline int read() {
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int N, M, L, rak[MAXN], tax[MAXN], tp[MAXN], sa[MAXN], H[MAXN], f[MAXN][20], lg2[MAXN];
    char s[MAXN], s0[MAXN];
    void Qsort() {
        for(int i = 0; i <= M; i++) tax[i] = 0;
        for(int i = 1; i <= N; i++) tax[rak[i]]++;
        for(int i = 1; i <= M; i++) tax[i] += tax[i - 1];
        for(int i = N; i >= 1; i--) sa[tax[rak[tp[i]]]--] = tp[i];
    }
    void SuffixSort() {
        for(int i = 1; i <= N; i++) rak[i] = s[i], tp[i] = i; M = 233; Qsort();
        for(int w = 1, p = 0; p < N; w <<= 1, M = p) { p = 0;
            for(int i = 1; i <= w; i++) tp[++p] = N - i + 1;
            for(int i = 1; i <= N; i++) if(sa[i] > w) tp[++p] = sa[i] - w;
            Qsort(); swap(tp, rak); rak[sa[1]] = p = 1;
            for(int i = 2; i <= N; i++) rak[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w]) ? p : ++p;
        }
        for(int i = 1, k = 0; i <= N; i++) {
            if(k) k--; int j = sa[rak[i] - 1];
            while(s[i + k] == s[j + k]) k++;
            H[rak[i]] = k;
        } 
    }
    void Pre() {
        for(int i = 1; i <= N; i++) f[i][0] = H[i];
        for(int j = 1; j <= 17; j++)
            for(int i = 1; i + (1 << j) - 1 <= N; i++) f[i][j] = min(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
    }
    int Query(int x, int y) {
        if(x > y) swap(x, y); x++;
        int k = lg2[y - x + 1];
        return min(f[x][k], f[y - (1 << k) + 1][k]);
    }
    int check(int x, int y, int dep) {
        if(dep == 3) return Query(rak[x], rak[y]);
        int num = Query(rak[x], rak[y]);
        num +=  check(x + num + 1, y + num + 1, dep + 1) + 1;
        return num;
    }
    void solve() {
        scanf("%s%s", s + 1, s0 + 1);
        L = strlen(s0 + 1); N = strlen(s + 1);
        for(int i = 1; i <= L; i++) s[N + i] = s0[i];
        N += L;
        SuffixSort(); Pre(); N -= L; int ans = 0;
        for(int i = 1; i <= N - L + 1; i++) if(check(i, N + 1, 0) >= L) ans++;
        printf("%d
    ", ans);
    }
    int main() {
        //freopen("a.in", "r", stdin);
        lg2[1] = 0; for(int i = 2; i <= MAXN - 1; i++) lg2[i] = lg2[i >> 1] + 1;
        for(int T = read(); T; solve(), T--);
        return 0;
    }
    /*
    2
    ATCGCCCTA
    CTTCA
    ATCGCCCTA
    CTTCA
    */
    
  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    SIP协议
    PAT (Basic Level) Practice 1008 数组元素循环右移问题
    LeetCode-Algorithms 1. 两数之和
    PAT (Basic Level) Practice 1040 有几个PAT
    PAT (Basic Level) Practice 1023 组个最小数
    PAT (Basic Level) Practice 1021 个位数统计
    PAT (Basic Level) Practice 1007 素数对猜想
    PAT (Basic Level) Practice 1006 换个格式输出整数
    PAT (Basic Level) Practice 1004 成绩排名
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/10033088.html
Copyright © 2011-2022 走看看