[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 }
以上是关于[HDU3518]Boring counting(后缀数组)的主要内容,如果未能解决你的问题,请参考以下文章
Boring counting HDU - 3518 (后缀数组)