zoukankan      html  css  js  c++  java
  • SPOJ DISUBSTR(后缀数组)

    传送门:DISUBSTR

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

    分析:对于每个sa[i]贡献n-a[i]个后缀,然后减去a[i]与a[i-1]的公共前缀height[i],则每个a[i]贡献n-sa[i]-height[i]个不同子串。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxn = 1010;
    
    int sa[maxn]; 
    int t1[maxn], t2[maxn], c[maxn];
    int rank[maxn], height[maxn];
    int s[maxn];
    char str[maxn];
    
    void build_sa(int s[], int n, int m) {
        int i, j, p, *x = t1, *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 (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]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p-1 : p++;
    
            if (p >= n) break;
            m = p;
        }
    }
    
    void getHeight(int s[],int n) {
        int i, j, k = 0;
        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 (s[i+k] == s[j+k]) k++;
            height[rank[i]]=k;
        }
    }
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) {
            scanf("%s", str);
            int n = strlen(str);
            for (int i = 0; i <= n; i++)
                s[i] = str[i];
            build_sa(s, n+1, 128);
            getHeight(s, n);
            int ans = 0;
            for (int i = 1; i <= n; i++)
                ans += n - sa[i] - height[i];
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    吴恩达 机器学习EX1学习笔记 MATLAB实现
    二分法解具有单调性的方程
    利用new定位运算符进行高效的数组动态增扩
    单循环链表基本操作及部分可能出现的细节问题
    数组中某元素的删除
    C# 实现可克隆(ICloneable)的类型
    Python学习十三
    Python学习十二
    Python学习十一
    Python学习十
  • 原文地址:https://www.cnblogs.com/lienus/p/4326845.html
Copyright © 2011-2022 走看看