zoukankan      html  css  js  c++  java
  • 【BZOJ4698】[SDOI2008]Sandy的卡片

    【BZOJ4698】[SDOI2008]Sandy的卡片

    题面

    flag倒了。

    bzoj

    洛谷

    题解

    首先题目的区间加很丑对吧,

    将每个串差分一下,就可以转化为

    求:

    给定(N)个串,求他们的最长公共子串。

    怎么办呢,按照后缀数组常用套路

    我们用不同的未曾用过的字符将这些串连接起来

    我们将(lcp)大于(mid)的串分组

    如果一组内串的个数大于等于(N)个,就证明可以(return;1)

    否则若没有一组大于等于(N)返回(0)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring> 
    #include <cmath> 
    #include <algorithm>
    using namespace std; 
    inline int gi() {
        register int data = 0, w = 1;
        register char ch = 0;
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar();
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
        return w * data; 
    }
    const int MAX_N = 2e6 + 5; 
    int N, T, a[MAX_N], b[MAX_N], vis[MAX_N]; 
    int sa[MAX_N], rnk[MAX_N], lcp[MAX_N]; 
    void GetSA() {
    #define cmp(i, j, k) (y[i] == y[j] && y[i + k] == y[j + k]) 
        static int x[MAX_N], y[MAX_N], bln[MAX_N];
        int M = 1e6; 
        for (int i = 1; i <= N; i++) bln[x[i] = a[i]]++; 
        for (int i = 1; i <= M; i++) bln[i] += bln[i - 1]; 
        for (int i = N; i >= 1; i--) sa[bln[x[i]]--] = i; 
        for (int k = 1; k <= N; k <<= 1) { 
            int p = 0; 
            for (int i = 0; i <= M; i++) y[i] = 0; 
            for (int i = N - k + 1; i <= N; i++) y[++p] = i; 
            for (int i = 1; i <= N; i++) if (sa[i] > k) y[++p] = sa[i] - k; 
            for (int i = 0; i <= M; i++) bln[i] = 0; 
            for (int i = 1; i <= N; i++) bln[x[y[i]]]++; 
            for (int i = 1; i <= M; i++) bln[i] += bln[i - 1]; 
            for (int i = N; i >= 1; i--) sa[bln[x[y[i]]]--] = y[i]; 
            swap(x, y); x[sa[1]] = p = 1; 
            for (int i = 2; i <= N; i++) x[sa[i]] = cmp(sa[i], sa[i - 1], k) ? p : ++p; 
            if (p >= N) break;
            M = p; 
        } 
    }
    void GetLcp() { 
        for (int i = 1; i <= N; i++) rnk[sa[i]] = i; 
        for (int i = 1, j = 0; i <= N; i++) {
            if (j) --j; 
            while (a[i + j] == a[sa[rnk[i] - 1] + j]) ++j; 
            lcp[rnk[i]] = j; 
        } 
    } 
    int col[MAX_N], tot; 
    bool check(int v) {
        ++tot; int cnt = 0; 
        for (int i = 1; i <= N; i++) { 
            if (lcp[i] < v) ++tot, cnt = 0; 
            if (col[vis[sa[i]]] != tot) col[vis[sa[i]]] = tot, ++cnt; 
            if (cnt == T) return 1; 
        } 
        return 0; 
    } 
    const int dlt = 5e4; 
    int main () { 
        T = gi(); 
        for (int i = 1; i <= T; i++) { 
            int m = gi(); 
            for (int j = 1; j <= m; j++) b[j] = gi(); 
            for (int j = 1; j <= m; j++) b[j] = b[j + 1] - b[j] + dlt; 
            for (int j = 1; j < m; j++) a[++N] = b[j], vis[N] = i; 
            a[++N] = i + 5e5; 
        }
        GetSA(); GetLcp(); 
        int l = 0, r = N, ans = 0; 
        while (l <= r) { 
            int mid = (l + r) >> 1; 
            if (check(mid)) l = mid + 1, ans = mid;
            else r = mid - 1; 
        } 
        printf("%d
    ", ans + 1); 
        return 0; 
    } 
    
  • 相关阅读:
    软件架构的认识
    软件需求十步走读书笔记3
    软件需求十步走读书笔记2
    系统利益相关者描述案例
    项目目标文档
    《需求工程-软件建模与分析》读书笔记2
    《需求工程-软件建模与分析》读书笔记1
    专业实训题目需求分析
    2015年秋季个人阅读计划
    课程改进意见
  • 原文地址:https://www.cnblogs.com/heyujun/p/10305521.html
Copyright © 2011-2022 走看看