Tuesday, December 3, 2019

[Toph] The Story of Stringland

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : The Story of Stringland
Source            : toph.co
Category          : String, Data Structure
Algorithm         : Suffix Array, Palindromic Tree
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. static const int maxn = 2e6 + 5;  
  6. static const int logn = 20;  
  7.   
  8. int p[maxn];  
  9. int pn[maxn];  
  10. int c[logn][maxn];  
  11. int cn[maxn];  
  12. int cnt[maxn];  
  13.   
  14. void sort_cyclic_shifts(string &s)  
  15. {  
  16.       int n = s.size();  
  17.       memset(cnt, 0, sizeof cnt);  
  18.       for (int i = 0; i < n; i++) cnt[ s[i] ]++;  
  19.       for (int i = 1; i < 256; i++) cnt[i] += cnt[i - 1];  
  20.       for (int i = 0; i < n; i++) p[ --cnt[ s[i] ] ] = i;  
  21.       int classes = 1;  
  22.       for (int i = 0; i < n; i++)  
  23.       {  
  24.             if (i && s[ p[i] ] != s[ p[i - 1] ]) classes++;  
  25.             c[0][ p[i] ] = classes - 1;  
  26.       }  
  27.       for (int k = 0; (1 << k) < n; k++)  
  28.       {  
  29.             for (int i = 0; i < n; i++)  
  30.             {  
  31.                   pn[i] = p[i] - (1 << k);  
  32.                   if (pn[i] < 0) pn[i] += n;  
  33.             }  
  34.             fill(cnt, cnt + classes, 0);  
  35.             for (int i = 0; i < n; i++) cnt[ c[k][ pn[i] ] ]++;  
  36.             for (int i = 1; i < classes; i++) cnt[i] += cnt[i - 1];  
  37.             for (int i = n - 1; i >= 0; i--) p[ --cnt[ c[k][ pn[i] ] ] ] = pn[i];  
  38.             classes = 1;  
  39.             cn[ p[0] ] = 0;  
  40.             pair <intint> x;  
  41.             pair <intint> y;  
  42.             for (int i = 1; i < n; i++)  
  43.             {  
  44.                   x = {c[k][ p[i] ], c[k][(p[i] + (1 << k)) % n]};  
  45.                   y = {c[k][ p[i - 1] ], c[k][(p[i - 1] + (1 << k)) % n]};  
  46.                   if (x != y) classes++;  
  47.                   cn[ p[i] ] = classes - 1;  
  48.             }  
  49.             for (int i = 0; i < n; i++) c[k + 1][i] = cn[i];  
  50.       }  
  51. }  
  52.   
  53. vector <int> suffix_array_construction(string s)  
  54. {  
  55.       s += "$";  
  56.       sort_cyclic_shifts(s);  
  57.       vector <int> sorted_shifts;  
  58.       int n = s.size();  
  59.       for (int i = 1; i < s.size(); i++) sorted_shifts.push_back(p[i]);  
  60.       return sorted_shifts;  
  61. }  
  62.   
  63. int compare(int i, int j, int substr_len, int n) // compare two equal length substring in O(1)  
  64. {  
  65.       // i = start index of first index  
  66.       // j = start index of second index  
  67.       // substr_len = length of sub-string  
  68.       // n = length of original string  
  69.       int k = __lg(substr_len);  
  70.       pair <intint> a = make_pair(c[k][i], c[k][(i + substr_len - (1 << k)) % n]);  
  71.       pair <intint> b = make_pair(c[k][j], c[k][(j + substr_len - (1 << k)) % n]);  
  72.       return a == b ? 0 : a < b ? -1 : 1;  
  73. }  
  74.   
  75. int longest_common_prefix(int i, int j)  
  76. {  
  77.       int ans = 0;  
  78.       for (int k = logn - 1; k >= 0; k--)  
  79.       {  
  80.             if (c[k][i] == c[k][j])  
  81.             {  
  82.                   ans += (1 << k);  
  83.                   i += (1 << k);  
  84.                   j += (1 << k);  
  85.             }  
  86.       }  
  87.       return ans;  
  88. }  
  89.   
  90. vector <int> lcp_construction(string const &s, vector <intconst &suffix_array)  
  91. {  
  92.       int n = s.size();  
  93.       vector <int> Rank(n, 0);  
  94.       for (int i = 0; i < n; i++) Rank[ suffix_array[i] ] = i;  
  95.       int k = 0;  
  96.       vector <int> lcp(n - 1, 0);  
  97.       for (int i = 0; i < n; i++)  
  98.       {  
  99.             if (Rank[i] == n - 1)  
  100.             {  
  101.                   k = 0;  
  102.                   continue;  
  103.             }  
  104.             int j = suffix_array[ Rank[i] + 1 ];  
  105.             while (i + k < n && j + k < n && s[i + k] == s[j + k]) k++;  
  106.             lcp[ Rank[i] ] = k;  
  107.             if (k) --k;  
  108.       }  
  109.       return lcp;  
  110. }  
  111.   
  112. struct PTree  
  113. {  
  114.       int next[27];  
  115.       int st;  
  116.       int len;  
  117.       int sufflink;  
  118.       PTree(int st = 0, int len = 0, int sufflink = 0)  
  119.             : st(st)  
  120.             , len(len)  
  121.             , sufflink(sufflink)  
  122.             {  
  123.                   memset(next, 0, sizeof next);  
  124.             }  
  125. };  
  126.   
  127. PTree Tree[maxn];  
  128. int num;  
  129. int suff;  
  130.   
  131. void init()  
  132. {  
  133.       for (int i = 0; i < maxn; i++) Tree[i] = PTree();  
  134.       num = 2;  
  135.       suff = 2;  
  136.       Tree[1].len = -1; Tree[1].sufflink = 1;  
  137.       Tree[2].len = 0; Tree[2].sufflink = 1;  
  138. }  
  139.   
  140. bool addLetter(string &s, int pos)  
  141. {  
  142.       int cur = suff;  
  143.       int curlen = 0;  
  144.       int let = s[pos] - 'a';  
  145.       while (true)  
  146.       {  
  147.             curlen = Tree[cur].len;  
  148.             if (pos - 1 - curlen >= 0 and s[pos - 1 - curlen] == s[pos]) break;  
  149.             cur = Tree[cur].sufflink;  
  150.       }  
  151.       if (Tree[cur].next[let])  
  152.       {  
  153.             suff = Tree[cur].next[let];  
  154.             return false;  
  155.       }  
  156.       ++num;  
  157.       suff = num;  
  158.       Tree[num].len = Tree[cur].len + 2;  
  159.       Tree[num].st = pos - Tree[num].len + 1;  
  160.       Tree[cur].next[let] = num;  
  161.       if (Tree[num].len == 1)  
  162.       {  
  163.             Tree[num].sufflink = 2;  
  164.             return true;  
  165.       }  
  166.       while (true)  
  167.       {  
  168.             cur = Tree[cur].sufflink;  
  169.             curlen = Tree[cur].len;  
  170.             if (pos - 1 - curlen >= 0 and s[pos - 1 - curlen] == s[pos])  
  171.             {  
  172.                   Tree[num].sufflink = Tree[cur].next[let];  
  173.                   break;  
  174.             }  
  175.       }  
  176.       return true;  
  177. }  
  178.   
  179. struct Info  
  180. {  
  181.       int st;  
  182.       int ed;  
  183.       Info(int st, int ed) : st(st), ed(ed) {}  
  184. };  
  185.   
  186. signed main()  
  187. {  
  188.       ios_base::sync_with_stdio(false);  
  189.       cin.tie(nullptr);  
  190.       cout.tie(nullptr);  
  191.   
  192.       #ifndef ONLINE_JUDGE  
  193.             freopen("in.txt""r", stdin);  
  194.       #endif // ONLINE_JUDGE  
  195.   
  196.   
  197.       string s;  
  198.       cin >> s;  
  199.       int n = s.size();  
  200.       init();  
  201.       for (int i = 0; i < n; i++) addLetter(s, i);  
  202.       vector <int> suffix_array = suffix_array_construction(s);  
  203.       vector <Info> vec;  
  204.       for (int i = 3; i <= num; i++)  
  205.       {  
  206.             vec.emplace_back(Tree[i].st, Tree[i].st + Tree[i].len - 1);  
  207.       }  
  208.       sort(vec.begin(), vec.end(), [&](Info &A, Info &B)  
  209.            {  
  210.                  int len1 = A.ed - A.st + 1;  
  211.                  int len2 = B.ed - B.st + 1;  
  212.                  int substr_len = min(len1, len2);  
  213.                  int val = compare(A.st, B.st, substr_len, n);  
  214.                  if (val == 0) return len1 < len2;  
  215.                  if (val == -1) return true;  
  216.                  return false;  
  217.            });  
  218.       int q;  
  219.       cin >> q;  
  220.       int sze = vec.size();  
  221.       while (q--)  
  222.       {  
  223.             int k;  
  224.             cin >> k;  
  225.             if (k > sze) cout << -1 << '\n';  
  226.             else cout << vec[k - 1].st + 1 << ' ' << vec[k - 1].ed + 1 << '\n';  
  227.       }  
  228. }  

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.