spoj694,spoj705 后缀数组/不相同的子串的个数 计算贡献

来源:互联网 发布:mac 游戏加速器 编辑:程序博客网 时间:2024/06/08 00:06


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]+1 个新 的前缀。 但是其中有
height[k]个是和前面的字符串的前缀是相同的。所以 suffix(sa[k])将“贡献”
出 n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。这个做法
的时间复杂度为 O(n)。



#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 100005;struct SuffixArray {  char s[maxn];      // 原始字符数组(最后一个字符应必须是0,而前面的字符必须非0)  int sa[maxn];     // 后缀数组  int rank1[maxn];   // 名次数组. rank[0]一定是n-1,即最后一个字符  int height[maxn]; // height数组  int t[maxn], t2[maxn], c[maxn]; // 辅助数组  int n; // 字符个数  void clear() { n = 0; memset(sa, 0, sizeof(sa)); }  // m为最大字符值加1。调用之前需设置好s和n  void build_sa(int m) {    int i, *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) {      int p = 0;      for(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];      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 build_height() {    int i, j, k = 0;    for(i = 0; i < n; i++) rank1[sa[i]] = i;    for(i = 0; i < n; i++) {      if(k) k--;      int j = sa[rank1[i]-1];      while(s[i+k] == s[j+k]) k++;      height[rank1[i]] = k;    }  }};SuffixArray sol;int T;int main(){//    freopen("data.txt","r",stdin);    ios_base::sync_with_stdio(false);    cin >> T;    while(T--)    {        memset(sol.s,0,sizeof(sol.s));        cin >> sol.s;        sol.clear();        sol.n = strlen(sol.s)+1;        sol.build_sa(130);//        for(int i=0;i<sol.n;i++)//        {//            cout << sol.sa[i]<<" ";//        }//        cout <<endl;        sol.build_height();//        sol.n--;        ll ans = 0 ;        for(int i=1;i<sol.n;i++)        {            ans += sol.n - sol.sa[i]-1 - sol.height[i];        }        cout << ans<<endl;    }    return 0;}


阅读全文
0 0