bzoj3230: 相似子串
这里给出了统计有效子串以及确定其第一次出现位置的方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<iostream> 6 7 using namespace std; 8 9 void setIO(const string& s) { 10 freopen((s + ".in").c_str(), "r", stdin); 11 freopen((s + ".out").c_str(), "w", stdout); 12 } 13 template<typename Q> Q read(Q& x) { 14 static char c, f; 15 for(f = 0; c = getchar(), !isdigit(c); ) if(c == '-') f = 1; 16 for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0'; 17 if(f) x = -x; 18 return x; 19 } 20 template<typename Q> Q read() { 21 static Q x; read(x); return x; 22 } 23 24 typedef long long LL; 25 const int N = 100000 + 10, INF = ~0u >> 1; 26 27 char s[N]; 28 int n, Log2[N]; 29 struct SuffixArray { 30 int sa[N]; 31 void build_sa(const char *s, int m = 256) { 32 static int t1[N], t2[N], c[N]; 33 int *x = t1, *y = t2; 34 for(int i = 0; i < m; i++) c[i] = 0; 35 for(int i = 0; i < n; i++) c[x[i] = s[i]]++; 36 for(int i = 1; i < m; i++) c[i] += c[i-1]; 37 for(int i = 0; i < n; i++) sa[--c[x[i]]] = i; 38 39 for(int k = 1; k < n; k <<= 1) { 40 int p = 0; 41 for(int i = n - k; i < n; i++) y[p++] = i; 42 for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k; 43 for(int i = 0; i < m; i++) c[i] = 0; 44 for(int i = 0; i < n; i++) c[x[i]]++; 45 for(int i = 1; i < m; i++) c[i] += c[i-1]; 46 for(int i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; 47 p = 1, swap(x, y), x[sa[0]] = 0; 48 for(int i = 1; i < n; i++) { 49 x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && (sa[i-1]+k < n ? y[sa[i-1]+k] : -1) == (sa[i]+k < n ? y[sa[i]+k] : -1)) ? p-1 : p++; 50 } 51 if(p >= n) break; 52 m = p; 53 } 54 } 55 56 int rank[N], height[N]; 57 58 void build_height(const char *s) { 59 for(int i = 0; i < n; i++) rank[sa[i]] = i; 60 for(int k = 0, i = 0; i < n; i++) { 61 if(k) k--; 62 if(!rank[i]) continue; 63 int j = sa[rank[i]-1]; 64 while(s[i+k] == s[j+k]) k++; 65 height[rank[i]] = k; 66 } 67 } 68 69 LL s[N]; 70 71 void build_s() { 72 s[0] = n - sa[0]; 73 for(int i = 1; i < n; i++) { 74 s[i] = s[i-1] + n - sa[i] - height[i]; 75 } 76 } 77 78 int f[N][17]; 79 80 void rmq_init() { 81 for(int i = 1; i < n; i++) f[i][0] = height[i]; 82 for(int j = 1; (1 << j) < n; j++) { 83 for(int i = 1; i + (1 << (j-1)) < n; i++) { 84 f[i][j] = min(f[i][j-1], f[i + (1 << (j-1))][j-1]); 85 } 86 } 87 } 88 89 int rmq(int a, int b) { 90 a = rank[a], b = rank[b]; 91 if(a > b) swap(a, b); ++a; 92 int t = Log2[b - a + 1]; 93 return min(f[a][t], f[b - (1 << t) + 1][t]); 94 } 95 96 void kthstr(LL pos, int& a, int& b) { 97 int x = lower_bound(s, s + n, pos) - s; 98 a = sa[x], b = sa[x] + height[x] + pos - (x ? s[x-1] : 0); 99 } 100 101 void init(const char *s) { 102 build_sa(s); 103 build_height(s); 104 build_s(); 105 rmq_init(); 106 } 107 }A, B; 108 109 int main() { 110 #ifdef DEBUG 111 freopen("in.txt", "r", stdin); 112 freopen("out.txt", "w", stdout); 113 #endif 114 Log2[0] = -1; 115 for(int i = 1; i < N; i++) Log2[i] = Log2[i >> 1] + 1; 116 117 int m; 118 read(n), read(m); 119 scanf("%s", s); 120 121 A.init(s); 122 reverse(s, s + n); 123 B.init(s); 124 125 while(m--) { 126 int a1, a2, b1, b2, t; 127 LL l, r, ans = 0; 128 read(l), read(r); 129 if(l > A.s[n-1] || r > A.s[n-1]) { 130 puts("-1"); 131 continue; 132 } 133 A.kthstr(l, a1, b1); 134 A.kthstr(r, a2, b2); 135 t = (a1 == a2) ? INF : A.rmq(a1, a2); 136 t = min(t, min(b1 - a1, b2 - a2)); 137 ans += (LL) t * t; 138 t = (b1 == b2) ? INF : B.rmq(n - b1, n - b2); 139 t = min(t, min(b1 - a1, b2 - a2)); 140 ans += (LL) t * t; 141 printf("%lld\n", ans); 142 } 143 144 return 0; 145 }
原文出处http://www.cnblogs.com/showson/