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

[HDU3518]Boring counting(后缀数组)

时间:2017-06-11 10:28:00      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:==   main   cli   传送门   cst   style   cstring   strlen   ret   

传送门

 

求出现超过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(后缀数组)

标签:==   main   cli   传送门   cst   style   cstring   strlen   ret   

原文地址:http://www.cnblogs.com/zhenghaotian/p/6984169.html

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