Advertisement
Guest User

Sherlock and Unique Substrings

a guest
Jun 23rd, 2015
405
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.36 KB | None | 0 0
  1. #include <algorithm>
  2. #include <string>
  3. #include <vector>
  4. #include <queue>
  5. #include <iostream>
  6. #include <cmath>
  7. #include <sstream>
  8. #include <map>
  9. #include <set>
  10. #include <numeric>
  11. #include <memory.h>
  12. #include <cstdio>
  13. #include <assert.h>
  14.  
  15. using namespace std;
  16.  
  17. #define pb push_back
  18. #define INF 1011111111
  19. #define FOR(i, a, b) for (int _n(b), i(a); i < _n; i++)
  20. #define rep(i, n) FOR(i, 0, n)
  21. #define CL(a, v) memset((a), (v), sizeof(a))
  22. #define mp make_pair
  23. #define X first
  24. #define Y second
  25. #define all(c) (c).begin(), (c).end()
  26. #define SORT(c) sort(all(c))
  27.  
  28. typedef long long ll;
  29. typedef vector<int> VI;
  30. typedef pair<int, int> pii;
  31.  
  32. /*** TEMPLATE CODE ENDS HERE */
  33.  
  34. const int maxn = 1e5 + 5;
  35. const int BLOCK = 320;
  36.  
  37. int classes[maxn];
  38. int sa[maxn];
  39. int lcp[maxn];
  40.  
  41. void BuildSuffixArray2(char *S, int n) {
  42.   static pair<pii, int> buff[2 * maxn + 10];
  43.  
  44.   rep(i, n) classes[i] = S[i];
  45.  
  46.   for (int k = 1; k <= n; k <<= 1) {
  47.     rep(i, n) buff[i] = mp(mp(classes[i], classes[(i + k) % n]), i);
  48.  
  49.     sort(buff, buff + n);
  50.     int C = 0;
  51.  
  52.     rep(i, n) {
  53.       if (!i || buff[i].X != buff[i - 1].X) {
  54.         C++;
  55.       }
  56.       classes[buff[i].Y] = C - 1;
  57.       sa[i] = buff[i].Y;
  58.     }
  59.   }
  60. }
  61.  
  62. const int kMaxAlphabet = 256;
  63.  
  64. int nsa[maxn];
  65. int nclasses[maxn];
  66. int p[maxn], cnt[maxn], c[maxn];
  67. int pn[maxn], cn[maxn];
  68.  
  69. void BuildSuffixArray(char *s, int n) {
  70.   memset(cnt, 0, kMaxAlphabet * sizeof(int));
  71.   for (int i = 0; i < n; ++i) ++cnt[s[i]];
  72.   for (int i = 1; i < kMaxAlphabet; ++i) cnt[i] += cnt[i - 1];
  73.   for (int i = kMaxAlphabet - 1; i >= 0; --i) cnt[i] = i > 0 ? cnt[i - 1] : 0;
  74.   for (int i = 0; i < n; ++i) p[cnt[s[i]]++] = i;
  75.   c[p[0]] = 0;
  76.   int classes = 1;
  77.   for (int i = 1; i < n; ++i) {
  78.     if (s[p[i]] != s[p[i - 1]]) ++classes;
  79.     c[p[i]] = classes - 1;
  80.   }
  81.  
  82.   for (int h = 0; (1 << h) < n; ++h) {
  83.     for (int i = 0; i < n; ++i) {
  84.       pn[i] = p[i] - (1 << h);
  85.       if (pn[i] < 0) pn[i] += n;
  86.     }
  87.     memset(cnt, 0, classes * sizeof(int));
  88.     for (int i = 0; i < n; ++i) ++cnt[c[pn[i]]];
  89.     for (int i = 1; i < classes; ++i) cnt[i] += cnt[i - 1];
  90.     for (int i = classes - 1; i >= 0; --i) cnt[i] = i > 0 ? cnt[i - 1] : 0;
  91.     for (int i = 0; i < n; ++i) p[cnt[c[pn[i]]]++] = pn[i];
  92.     cn[p[0]] = 0;
  93.     classes = 1;
  94.     for (int i = 1; i < n; ++i) {
  95.       int mid1 = (p[i] + (1 << h)) % n, mid2 = (p[i - 1] + (1 << h)) % n;
  96.       if (c[p[i]] != c[p[i - 1]] || c[mid1] != c[mid2]) ++classes;
  97.       cn[p[i]] = classes - 1;
  98.     }
  99.     memcpy(c, cn, n * sizeof(int));
  100.   }
  101.   rep(i, n) sa[i] = p[i];
  102. }
  103.  
  104. static int isa[maxn];
  105.  
  106. void BuildLcp(char *S, int n) {
  107.   rep(i, n) isa[sa[i]] = i;
  108.  
  109.   int L = 0;
  110.   rep(i, n) {
  111.     L = max(0, L - 1);
  112.     if (isa[i] + 1 < n) {
  113.       int nxt = sa[isa[i] + 1];
  114.       while (S[i + L] == S[nxt + L]) ++L;
  115.     }
  116.     lcp[isa[i]] = L;
  117.   }
  118. }
  119.  
  120. struct Query {
  121.   int l, r, idx;
  122. };
  123.  
  124. bool cmp(const Query &A, const Query &B) {
  125.   if (A.l / BLOCK != B.l / BLOCK) return A.l / BLOCK < B.l / BLOCK;
  126.   return A.r > B.r;
  127. }
  128.  
  129. char s[maxn];
  130.  
  131. Query q[maxn];
  132.  
  133. ll ans[maxn];
  134.  
  135. ll tr1[maxn];
  136. ll tr2[maxn];
  137.  
  138. int N;
  139. void update(ll tr[], int i, ll by) {
  140.   for (++i; i <= N; i += -i & i) tr[i] += by;
  141. }
  142.  
  143. void update(int a, int b, int by) {
  144.   update(tr1, a, by);
  145.   update(tr1, b + 1, -by);
  146.   update(tr2, a, by * (a - 1));
  147.   update(tr2, b + 1, -by * b);
  148. }
  149.  
  150. ll query(ll tr[], int i) {
  151.   ll s = 0;
  152.   for (++i; i > 0; i -= -i & i) s += tr[i];
  153.   return s;
  154. }
  155.  
  156. ll query(int x) { return query(tr1, x) * x - query(tr2, x); }
  157.  
  158. ll query(int a, int b) { return query(b) - query(a); }
  159.  
  160. void remove(int i) {
  161.   int r = isa[i];
  162.   int common = lcp[r];
  163.   if (r > 0) common = max(common, lcp[r - 1]);
  164.   int len = N - i;
  165.  
  166.   update(i + common, i + len - 1, -1);
  167. }
  168.  
  169. void add(int i) {
  170.   int r = isa[i];
  171.   int common = lcp[r];
  172.   if (r > 0) common = max(common, lcp[r - 1]);
  173.   int len = N - i;
  174.  
  175.   // add 1 to range [i + common, i + len - 1]
  176.   update(i + common, i + len - 1, 1);
  177. }
  178.  
  179. int main() {
  180. #ifdef LOCAL_HOST
  181.   freopen("input.txt", "r", stdin);
  182. // freopen("output.txt","w",stdout);
  183. #endif
  184.  
  185.   scanf("%s", s);
  186.   int Q = 0;
  187.   scanf("%d", &Q);
  188.   rep(i, Q) {
  189.     scanf("%d %d", &q[i].l, &q[i].r);
  190.     q[i].idx = i;
  191.     q[i].l--;
  192.     q[i].r--;
  193.   }
  194.  
  195.   sort(q, q + Q, cmp);
  196.  
  197.   int n = (int)strlen(s);
  198.   N = n;
  199.   s[n++] = '#';
  200.  
  201.   BuildSuffixArray(s, n);
  202.   BuildLcp(s, n);
  203.   --n;
  204.  
  205.   //  FOR(i, 1, n + 1) {
  206.   //    FOR(j, sa[i], n) cout << s[j];
  207.   //    cout << " " << lcp[i];
  208.   //    cout << endl;
  209.   //  }
  210.  
  211.   //  printf("%s\n", s);
  212.   //  rep(i, n) {
  213.   //    int r = isa[i];
  214.   //    int common = lcp[r];
  215.   //    if (r > 0) common = max(common, lcp[r - 1]);
  216.   //    printf("%d %d ", common, n - i);
  217.   //    FOR(j, sa[r], n) cout << s[j];
  218.   //    cout << endl;
  219.   //  }
  220.  
  221.   int currentL = 0, currentR = 0;
  222.   rep(i, Q) {
  223.     int L = q[i].l, R = q[i].r;
  224.  
  225.     while (currentL < L) {
  226.       remove(currentL);
  227.       currentL++;
  228.     }
  229.     while (currentL > L) {
  230.       add(currentL - 1);
  231.       currentL--;
  232.     }
  233.     while (currentR <= R) {
  234.       add(currentR);
  235.       currentR++;
  236.     }
  237.     while (currentR > R + 1) {
  238.       remove(currentR - 1);
  239.       currentR--;
  240.     }
  241.     ans[q[i].idx] = query(currentL, currentR - 1);
  242.   }
  243.  
  244.   rep(i, Q) cout << ans[i] << endl;
  245.  
  246. #ifdef LOCAL_HOST
  247.   printf("TIME: %.3lf\n", double(clock()) / CLOCKS_PER_SEC);
  248. #endif
  249.  
  250.   return 0;
  251. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement