码迷,mamicode.com
首页 > 编程语言 > 详细

Distinct Substrings (spoj694)(后缀数组)

时间:2019-01-17 17:45:32      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:using   bre   set   ++   line   wap   class   tin   数组   

核心:每一个后缀的每一个前缀都是一个子串

相邻后缀的lcp的值是就是重复子串的个数

用所有的子串减去sigma(height)就行了

 

 1 #include"bits/stdc++.h"
 2 using namespace std;
 3 #define clr(x) memset(x,0,sizeof(x))
 4 
 5 int T;
 6 char a[2000];
 7 int n,m;
 8 int x[2000],y[2000],c[2000];
 9 int sa[2000];
10 int rk[2000];
11 int ht[2000];
12 
13 inline void SA()
14 {
15    //cout<<"%^("<<endl;
16 
17    // cout<<n<<" "<<m<<endl;
18  //cout<<a+1<<endl;
19    /* memset(c,0,sizeof c);
20     memset(x,0,sizeof x);
21     memset(y,0,sizeof y);*/
22     clr(c);
23     clr(x);
24     clr(y);
25 
26 
27    for (int i=1;i<=n;i++) ++c[x[i] = a[i]-A];
28    for (int i=1;i<=m;i++) c[i]+=c[i-1];
29    for (int i=n;i;i--) sa[c[x[i]]--] = i;
30 
31    for (int k=1;k<=n;k*=2)
32    {
33 
34       int num = 0;
35       for (int i=n-k+1;i<=n;i++) y[++num] = i;
36       for (int i=1;i<=n;i++) if (sa[i]>k) y[++num] = sa[i]-k;
37       memset(c,0,sizeof c);
38       for (int i=1;i<=n;i++) ++c[x[y[i]]];
39       for (int i=1;i<=m;i++) c[i]+=c[i-1];
40       for (int i=n;i;i--) sa[c[x[y[i]]]--] = y[i],y[i]=0;
41       num=1;
42       swap(x,y);
43       x[sa[1]]=1;
44 
45       for (int i=2;i<=n;i++)
46       {
47         x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
48       }
49 
50       if (num==n) break;
51       m=num;
52 
53 
54    }
55 
56    for (int i=1;i<=n;i++) rk[sa[i]] = i;
57    int k = 0;
58 
59    for (int i=1;i<=n;i++)
60    {
61       if (rk[i]==1) continue;
62       if (k) k--;
63       int j =sa[rk[i]-1];
64 
65 
66       while (a[i+k]==a[j+k]&&i+k<=n&&j+k<=n) k++;
67 
68       ht[rk[i]] = k;
69    }
70 
71 //
72    //  for (int i=1;i<=n;i++ ) cout<<ht[i]<<" ";cout<<endl;
73   // /   / for (int i=1;i<=n;i++) cout<<sa[i]<<" ";cout<<endl;
74 
75 
76 }
77 
78 
79 
80 int main()
81 {
82   cin>>T;
83   while (T--)
84   {
85 
86     m=233;
87     cin>>a+1;
88     n = strlen(a+1);
89     SA();
90 
91   int ans = n*(n+1)/2;
92   for (int i=1;i<=n;i++ ) ans -= ht[i];
93   cout<<ans<<endl;
94 
95 
96 
97   }

 

Distinct Substrings (spoj694)(后缀数组)

标签:using   bre   set   ++   line   wap   class   tin   数组   

原文地址:https://www.cnblogs.com/zhangbuang/p/10283243.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!