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

    题目链接:http://www.spoj.com/problems/DISUBSTR/en/

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

    思路:直接根据09年oi论文<<后缀数组——出来字符串的有力工具>>的解法。

    还有另一种思想:总数为n*(n-1)/2,height[i]是两个后缀的最长公共前缀,所以用总数-height[i]的和就是答案

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<queue>
    #include<vector>
    #include<time.h>
    #include<cmath>
    using namespace std;
    typedef long long int LL;
    const int MAXN = 1000 + 5;
    int cmp(int *r, int a, int b, int l){
        return r[a] == r[b] && r[a + l] == r[b + l];
    }
    int wa[MAXN], wb[MAXN], wv[MAXN], WS[MAXN];
    void da(int *r, int *sa, int n, int m){
        int i, j, p, *x = wa, *y = wb, *t;
        for (i = 0; i<m; i++) WS[i] = 0;
        for (i = 0; i<n; i++) WS[x[i] = r[i]]++;
        for (i = 1; i<m; i++) WS[i] += WS[i - 1];
        for (i = n - 1; i >= 0; i--) sa[--WS[x[i]]] = i;
        for (j = 1, p = 1; p<n; j *= 2, m = p)
        {
            for (p = 0, 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<n; i++) wv[i] = x[y[i]];
            for (i = 0; i<m; i++) WS[i] = 0;
            for (i = 0; i<n; i++) WS[wv[i]]++;
            for (i = 1; i<m; i++) WS[i] += WS[i - 1];
            for (i = n - 1; i >= 0; i--) sa[--WS[wv[i]]] = y[i];
            for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i<n; i++)
                x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
        }
        return;
    }
    int Rank[MAXN], height[MAXN],sa[MAXN];
    void calheight(int *r, int *sa, int n){
        int i, j, k = 0;
        for (i = 1; i <= n; i++) Rank[sa[i]] = i;
        for (i = 0; i < n; height[Rank[i++]] = k)
            for (k ? k-- : 0, j = sa[Rank[i] - 1]; r[i + k] == r[j + k]; k++);
        return;
    }
    void solve(int n){
        int ans = 0;
        for (int i = 1; i <= n; i++){ 
            ans += ((n - 1) - sa[i] + 1 - height[i]);
            //(n-1)的原因,因为在最后加了一个原理字符串不存在的最小值
            //0,所以字符串原始长度为n-1
        }
        printf("%d
    ", ans);
    }
    int t, len,r[MAXN];
    char str[MAXN];
    int main(){
    //#ifdef kirito
    //    freopen("in.txt","r",stdin);
    //    freopen("out.txt","w",stdout);
    //#endif
    //    int start = clock();
        scanf("%d", &t);
        while (t--){
            scanf("%s", str); len = strlen(str); 
            for (int i = 0; i <= len; i++){ 
                if (i == len){ r[i] = 0; continue; } //字符串最后添加一个
                //小于所以字符的值
                r[i] = (int)str[i];
            } 
            da(r, sa, len+1, 256); 
            calheight(r, sa, len);
            solve(len);
        }
    //#ifdef LOCAL_TIME
    //    cout << "[Finished in " << clock() - start << " ms]" << endl;
    //#endif
        return 0;
    }
  • 相关阅读:
    CodeForces Gym 100935G Board Game DFS
    CodeForces 493D Vasya and Chess 简单博弈
    CodeForces Gym 100935D Enormous Carpet 快速幂取模
    CodeForces Gym 100935E Pairs
    CodeForces Gym 100935C OCR (水
    CodeForces Gym 100935B Weird Cryptography
    HDU-敌兵布阵
    HDU-Minimum Inversion Number(最小逆序数)
    七月馒头
    非常可乐
  • 原文地址:https://www.cnblogs.com/kirito520/p/5750836.html
Copyright © 2011-2022 走看看