zoukankan      html  css  js  c++  java
  • 后缀数组 SPOJ 694 Distinct Substrings

    题目链接

    题意:给定一个字符串,求不相同的子串的个数

    分析:我们能知道后缀之间相同的前缀的长度,如果所有的后缀按照 suffix(sa[0]), suffix(sa[1]), suffix(sa[2]), …… ,suffix(sa[n])的顺序计算,不难发现,对于每一次新加进来的后缀 suffix(sa[k]),它将产生 n-sa[k]+1 个新的前缀。但是其中有 height[k]个是和前面的字符串的前缀是相同的。所以 suffix(sa[k])将“贡献” 出 n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。

    这个”贡献“是不会重叠的,因为每次加的都是对于当前来说是没有与之相同的子串。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    const int N = 1e3 + 5;
    int sa[N], rank[N], height[N];
    int t[N], t2[N], c[N];
    char s[N];
    
    void da(char *s, int n, int m = 128) {
        int i, p, *x = t, *y = t2;
        for (i=0; i<m; ++i) c[i] = 0;
        for (i=0; i<n; ++i) c[x[i]=s[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 (int k=1; k<=n; k<<=1) {
            for (p=0, i=n-k; i<n; ++i) y[p++] = i;
            for (i=0; i<n; ++i) if (sa[i] >= k) y[p++] = sa[i] - k;
            for (i=0; i<m; ++i) c[i] = 0;
            for (i=0; i<n; ++i) c[x[y[i]]]++;
            for (i=0; i<m; ++i) c[i] += c[i-1];
            for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
            std::swap (x, y);
            p = 1; x[sa[0]] = 0;
            for (i=1; i<n; ++i) {
                x[sa[i]] = (y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k] ? p - 1 : p++);
            }
            if (p >= n) break;
            m = p;
        }
    }
    
    void calc_height(int n) {
        int i, k = 0;
        for (i=0; i<n; ++i) rank[sa[i]] = i;
        for (i=0; i<n; ++i) {
            if (k) k--;
            int j = sa[rank[i]-1];
            while (s[i+k] == s[j+k]) k++;
            height[rank[i]] = k;
        }
    }
    
    int n;
    
    int main() {
        int T; scanf ("%d", &T);
        while (T--) {
            scanf ("%s", s);
            n = strlen (s);
            n++;
            da (s, n);
            calc_height (n);
            int ans = 0;
            for (int i=0; i<n; ++i) {
                ans += n - sa[i] - 1 - height[i];
            }
            printf ("%d
    ", ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    POJ 2175 Evacuation Plan 费用流 负圈定理
    POJ 2983 Is the Information Reliable? 差分约束
    codeforces 420B Online Meeting
    POJ 3181 Dollar Dayz DP
    POJ Ant Counting DP
    POJ 1742 Coins DP 01背包
    中国儒学史
    产品思维30讲
    Java多线程编程核心技术
    编写高质量代码:改善Java程序的151个建议
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5450042.html
Copyright © 2011-2022 走看看