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;
    }
    

      

  • 相关阅读:
    【基础知识七】贝叶斯分类器
    tensorflow入门资料
    机器学习常用开发工具【转】
    SVM的sklearn.svm.SVC实现与类参数
    从线性回归到CNN【转】
    RBF神经网络和BP神经网络的关系
    sklearn安装
    【转】SQL模糊查询
    笔记:XML-解析文档-流机制解析器(SAX、StAX)
    笔记:XML-解析文档-XPath 定位信息
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5450042.html
Copyright © 2011-2022 走看看