zoukankan      html  css  js  c++  java
  • hdu-6194 string string string 后缀数组 出现恰好K次的串的数量

     最少出现K次我们可以用Height数组的lcp来得出,而恰好出现K次,我们只要除去最少出现K+1次的lcp即可。

    #include <cstdio>  
    #include <cstring>  
    #include <algorithm>  
    #include <iostream>
    using namespace std;
    
    const int maxn = 100000 + 10;
    
    int t1[maxn], t2[maxn], c[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 str[], int sa[], int Rank[], int lcp[], int n, int m) {
        ++n;
        int i, j, p, *x = t1, *y = t2;
        for (i = 0; i < m; ++i) c[i] = 0;
        //        puts("hha");  
        for (i = 0; i < n; ++i) c[x[i] = str[i]]++;
        for (i = 1; i < m; ++i) c[i] += c[i - 1];
        for (i = n - 1; i >= 0; --i) sa[--c[x[i]]] = i;
        for (j = 1; j <= n; j <<= 1) {
            p = 0;
            for (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 < m; ++i) c[i] = 0;
            for (i = 0; i < n; ++i) c[x[y[i]]]++;
    
            for (i = 1; i < m; ++i) c[i] += c[i - 1];
            for (i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i];
    
            swap(x, y);
            p = 1; x[sa[0]] = 0;
            for (i = 1; i < n; ++i) {
                x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
            }
            if (p >= n)break;
            m = p;
        }
    
        int k = 0;
        n--;
        for (i = 0; i <= n; ++i) Rank[sa[i]] = i;
        for (i = 0; i < n; ++i) {
            if (k)--k;
            j = sa[Rank[i] - 1];
            while (str[i + k] == str[j + k])++k;
            lcp[Rank[i]] = k;
            //cout << k << endl;
        }
    }
    
    int lcp[maxn], a[maxn], sa[maxn], Rank[maxn];
    
    char s[maxn];
    
    int d[maxn][40];
    int len;
    
    void rmq_init(int* A, int n) {
        for (int i = 0; i < n; ++i) d[i][0] = A[i];
        for (int j = 1; (1 << j) <= n; ++j)
            for (int i = 0; i + (1 << j) - 1 < n; ++i)
                d[i][j] = min(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
    }
    
    int ASK(int l, int r) {
        int k = 0;
        while ((1 << (k + 1)) <= r - l + 1)++k;
        return min(d[l][k], d[r - (1 << k) + 1][k]);
    }
    
    int ask(int l, int r) {
        if (l == r) return len - sa[r]; /// l == r的话 是一个串, 返回本身的长度即可。  
        return ASK(l + 1, r); ///否则在rmq查询。  
    }
    
    //  
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("outstd.txt", "w", stdout);
        int T;
        scanf("%d", &T);
        while (T--) {
            int k;
            scanf("%d", &k);
            scanf("%s", s);
            //puts(s);
            len = strlen(s);
            for (int i = 0; i < len; ++i) {
                a[i] = s[i] - 'a' + 1;
            }
            a[len] = 0;
            da(a, sa, Rank, lcp, len, 30);
            rmq_init(lcp, len + 1);
            long long ans = 0;
            if (k == 1)
            {
                for (int i = 1; i <= len; i++)
                {
                    int siz = len - sa[i];
                    int des = 0;
                    if (i > 1) des = max(des, ask(i - 1, i));
                    if (i < len) des = max(des, ask(i, i + 1));
                    ans += siz - des;
                }
            }
            else
            {
                for (int i = 1; i+k-1 <= len; i++)
                {
                    int siz = ask(i, i + k - 1);
                    int des = 0;
                    if (i > 1) des = max(des, ask(i - 1, i + k - 1));
                    if (i + k <= len) des = max(des, ask(i, i + k));
                    ans += siz - des;
                }
            }
            printf("%I64d
    ", ans);
            /*
            long long ans = 0;
    
            for (int i = 1; i + k - 1 <= len; ++i) {
                ans += ask(i, i + k - 1);
                if (i - 1 > 0)ans -= ask(i - 1, i + k - 1); ///注意边界问题。  
                if (i + k <= len)ans -= ask(i, i + k);
                if (i - 1 > 0 && i + k <= len)ans += ask(i - 1, i + k);
            }
            printf("%I64d
    ", ans);*/
    
    
        }
        return 0;
    }
  • 相关阅读:
    python 四舍五入
    Elasticsearch 入门
    Mac下ElasticSearch安装、Kibana
    Mysql 终端中文显示乱码
    Zookeeper 在 Kafka 中的作用
    mac 安装Kafka
    Creating a NuGet Package in 7 easy steps
    Updating and Publishing a NuGet Package
    ASP.NET Core 发布
    An entry point cannot be marked with the 'async' modifier
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/7553486.html
Copyright © 2011-2022 走看看