[HDU3518]Boring counting(后缀数组)

Posted 蒟蒻zht的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDU3518]Boring counting(后缀数组)相关的知识,希望对你有一定的参考价值。

传送门

 

求出现超过1次的不重叠子串的个数

 

根据论文中的方法。

枚举子串的长度 k。

用 k 给 height 数组分组,每一组求解,看看当前组的位置最靠后的后缀和位置最靠前的后缀所差个数是否大于长度,大于的话 ans++。

分组思想需要认真体会一下。

 

——代码

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 1005
 5 #define max(x, y) ((x) > (y) ? (x) : (y))
 6 #define min(x, y) ((x) < (y) ? (x) : (y))
 7 
 8 int len, n, m, ans;
 9 int buc[N], x[N], y[N], sa[N], ran[N], height[N];
10 char s[N];
11 
12 inline void build_sa()
13 {
14     int i, k, p;
15     for(i = 0; i < m; i++) buc[i] = 0;
16     for(i = 0; i < len; i++) buc[x[i] = s[i]]++;
17     for(i = 1; i < m; i++) buc[i] += buc[i - 1];
18     for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i;
19     for(k = 1; k <= len; k <<= 1)
20     {
21         p = 0;
22         for(i = len - 1; i >= len - k; i--) y[p++] = i;
23         for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
24         for(i = 0; i < m; i++) buc[i] = 0;
25         for(i = 0; i < len; i++) buc[x[y[i]]]++;
26         for(i = 1; i < m; i++) buc[i] += buc[i - 1];
27         for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i];
28         std::swap(x, y);
29         p = 1, x[sa[0]] = 0;
30         for(i = 1; i < len; i++)
31             x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
32         if(p >= len) break;
33         m = p;
34     }
35 }
36 
37 inline void build_height()
38 {
39     int i, j, k = 0;
40     for(i = 0; i < len; i++) ran[sa[i]] = i;
41     for(i = 0; i < len; i++)
42     {
43         if(!ran[i]) continue;
44         if(k) k--;
45         j = sa[ran[i] - 1];
46         while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++;
47         height[ran[i]] = k;
48     }
49 }
50 
51 inline void check(int k)
52 {
53     int Max, Min;
54     Max = Min = sa[0];
55     for(int i = 1; i < len; i++)
56         if(height[i] >= k)
57         {
58             Max = max(Max, sa[i]);
59             Min = min(Min, sa[i]);
60         }
61         else
62         {
63             ans += Max - Min >= k;
64             Max = Min = sa[i];
65         }
66     ans += Max - Min >= k;
67 }
68 
69 int main()
70 {
71     while(scanf("%s", s) != EOF)
72     {
73         if(s[0] == #) break;
74         len = strlen(s);
75         m = 300;
76         build_sa();
77         build_height();
78         ans = 0;
79         for(int i = 1; i <= (len >> 1); i++) check(i);
80         printf("%d\n", ans);
81     }
82     return 0;
83 }
View Code

 

以上是关于[HDU3518]Boring counting(后缀数组)的主要内容,如果未能解决你的问题,请参考以下文章

[HDU]3518——Boring counting

HDU3518 Boring counting

hdu3518 Boring Counting[后缀排序]

Boring counting HDU - 3518 (后缀数组)

[HDU3518]Boring counting(后缀数组)

hdu 3518 Boring counting 后缀数组 height分组