bzoj3230: 相似子串

这里给出了统计有效子串以及确定其第一次出现位置的方式

 

  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 }
View Code

 

posted @ 2015-12-27 20:23  Showson  阅读(157)  评论(0编辑  收藏  举报