程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> SPOJ - DISUBSTR Distinct Substrings(後綴數組求不相同的子串個數)

SPOJ - DISUBSTR Distinct Substrings(後綴數組求不相同的子串個數)

編輯:C++入門知識

SPOJ - DISUBSTR Distinct Substrings(後綴數組求不相同的子串個數)


Description

Given a string, we need to find the total number of its distinct substrings.

Input

T- number of test cases. T<=20;
Each test case consists of one string, whose length is <= 1000

Output

For each test case output one number saying the number of distinct substrings.

Example

Sample Input:
2
CCCCC
ABABA

Sample Output:
5
9

Explanation for the testcase with string ABABA:
len=1 : A,B
len=2 : AB,BA
len=3 : ABA,BAB
len=4 : ABAB,BABA
len=5 : ABABA
Thus, total number of distinct substrings is 9.

題意:給定一個字符串,求不相同的子串。
思路:每個子串一定是某個後綴的前綴,那麼原問題等價於求所有後綴之間的不相同的前綴的個數。如果所有的後綴按照 suffix(sa[1]), suffix(sa[2]),
suffix(sa[3]), …… ,suffix(sa[n])的順序計算,不難發現,對於每一次新加
進來的後綴 suffix(sa[k]),它將產生 n-sa[k]個新的前綴。但是其中有height[k]個是和前面的字符串的前綴是相同的。所以 suffix(sa[k])將“貢獻”
出 n-sa[k]-height[k]個不同的子串。累加後便是原問題的答案。

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 1010;

int sa[maxn]; //SA數組,表示將S的n個後綴從小到大排序後把排好序的
//的後綴的開頭位置順次放入SA中
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 check(int n, int k, int mid) {
    int num = 1;
    for (int i = 2; i <= n; i++) {
        if (height[i] >= mid) {
            num++;
            if (num >= k) return 1;
        }
        else num = 1;
    }
    return 0;
}

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\n", ans);
    }
    return 0;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved