Advertisement
Saleh127

SPOJ SUBLEX / Suffix Array - Template(shefin.cse)

Jan 8th, 2023
1,229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.49 KB | None | 0 0
  1. /***
  2.  created: 2023-01-09-02.03.49
  3. ***/
  4.  
  5. #include <bits/stdc++.h>
  6. #include <ext/pb_ds/assoc_container.hpp>
  7. #include <ext/pb_ds/tree_policy.hpp>
  8. using namespace std;
  9. using namespace __gnu_pbds;
  10. template<typename U> using ordered_set=tree<U, null_type,less<U>,rb_tree_tag,tree_order_statistics_node_update>;
  11. #define ll long long
  12. #define all(we) we.begin(),we.end()
  13. #define test int tt; cin>>tt; for(int cs=1;cs<=tt;cs++)
  14. #define nl '\n'
  15.  
  16. #define MAX_N 1000020
  17. int n, t;
  18. string s;
  19. int SA[MAX_N], LCP[MAX_N];
  20. int RA[2*MAX_N], tempRA[MAX_N];
  21. int tempSA[MAX_N];
  22. int c[MAX_N];
  23. int Phi[MAX_N], PLCP[MAX_N];
  24.  
  25. void countingSort(int k) {    // O(n)
  26.     int i, sum, maxi = max(300, n);
  27.     // up to 255 ASCII chars or length of n
  28.     memset(c, 0, sizeof c);
  29.     // clear frequency table
  30.     for (i = 0; i < n; i++)
  31.     // count the frequency of each integer rank
  32.     c[i + k < n ? RA[i + k] : 0]++;
  33.     for (i = sum = 0; i < maxi; i++) {
  34.         int t = c[i]; c[i] = sum; sum += t;
  35.     }
  36.     for (i = 0; i < n; i++)
  37.         // shuffle the suffix array if necessary
  38.         tempSA[c[SA[i] + k < n ? RA[SA[i] + k] : 0]++] = SA[i];
  39.  
  40.     for (i = 0; i < n; i++)
  41.         // update the suffix array SA
  42.         SA[i] = tempSA[i];
  43. }
  44.  
  45. void buildSA() {
  46.     int i, k, r;
  47.     for (i = 0; i < 2*n; i++) RA[i] = i<n? s[i] : 0;
  48.     // initial rankings
  49.     for (i = 0; i < n; i++) SA[i] = i;
  50.     // initial SA: {0, 1, 2, ..., n-1}
  51.     for (k = 1; k < n; k <<= 1) {
  52.         // repeat sorting process log n times
  53.         countingSort(k); // actually radix sort: sort based on the second item
  54.         countingSort(0);
  55.         // then (stable) sort based on the first item
  56.         tempRA[SA[0]] = r = 0;
  57.         // re-ranking; start from rank r = 0
  58.         for (i = 1; i < n; i++)
  59.             // compare adjacent suffixes
  60.             tempRA[SA[i]] = // if same pair => same rank r; otherwise, increase r
  61.                 (RA[SA[i]] == RA[SA[i - 1]] && RA[SA[i] + k] == RA[SA[i - 1] + k]) ? r : ++r;
  62.         for (i = 0; i < n; i++)
  63.             // update the rank array RA
  64.             RA[i] = tempRA[i];
  65.  
  66.         if (RA[SA[n - 1]] == n - 1) break;
  67.         // nice optimization trick
  68.     }
  69. }
  70.  
  71. void buildLCP() {
  72.     int i, L;
  73.     Phi[SA[0]] = -1;
  74.     // default value
  75.     for (i = 1; i < n; i++)
  76.         // compute Phi in O(n)
  77.         Phi[SA[i]] = SA[i - 1];
  78.     // remember which suffix is behind this suffix
  79.     for (i = L = 0; i < n; i++) {
  80.         // compute Permuted LCP in O(n)
  81.         if (Phi[i] == -1) { PLCP[i] = 0; continue; }
  82.         // special case
  83.         while (s[i + L] == s[Phi[i] + L]) L++;
  84.         // L increased max n times
  85.         PLCP[i] = L;
  86.         L = max(L - 1, 0);
  87.         // L decreased max n times
  88.     }
  89.     for (i = 0; i < n; i++)
  90.         // compute LCP in O(n)
  91.         LCP[i] = PLCP[SA[i]];
  92.         // put the permuted LCP to the correct position
  93. }
  94. // n = string length + 1
  95. // SA[0] holds the empty suffix "\0".
  96.  
  97.  
  98. int main()
  99. {
  100.     ios_base::sync_with_stdio(0);
  101.     cin.tie(0);
  102.     cout.tie(0);
  103.  
  104.     ll q,m,i,j,k,l;
  105.  
  106.     cin>>s;
  107.  
  108.     n=s.size()+1;
  109.  
  110.     buildSA();
  111.     buildLCP();
  112.  
  113.     cin>>q;
  114.  
  115.     while(q--)
  116.     {
  117.         cin>>k;
  118.  
  119.         ll ans=0;
  120.  
  121.         j=0;
  122.  
  123.         for(i=1;i<n;i++)
  124.         {
  125.             ans+=(n-1-SA[i]-LCP[i]);
  126.             if(ans>=k)
  127.             {
  128.                 j=i;
  129.                 break;
  130.             }
  131.         }
  132.  
  133.         for(i=SA[j];i<(n-1-ans+k);i++) cout<<s[i];
  134.  
  135.         cout<<nl;
  136.     }
  137.  
  138.  
  139.  
  140.     return 0;
  141. }
  142.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement