Monday, January 21, 2019

[UVa] 12206 - Stammering Aliens

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : 12206 - Stammering Aliens
Source            : UVA Online Judge
Category          : String, Data Structure
Algorithm         : Suffix Array, Segment Tree
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. #define FAST             ios_base::sync_with_stdio(false), cin.tie(nullptr);  
  6.   
  7. static const int maxn = 40000 + 5;  
  8. static const int logn = 18;  
  9. static const int inf = 12345678;  
  10.   
  11. struct entry  
  12. {  
  13.       int first, second;  
  14.       int p;  
  15.       entry(int ff = 0, int ss = 0, int pp = 0) : first(ff), second(ss), p(pp) {}  
  16.       friend bool operator < (const entry &A, const entry &B)  
  17.       {  
  18.             if (A.first == B.first) return A.second < B.second;  
  19.             return A.first < B.first;  
  20.       }  
  21. } L[maxn];  
  22.   
  23. int P[logn][maxn], B[maxn];  
  24. int p, q;  
  25. int step, lcp[maxn];  
  26.   
  27. inline int comp2(const int &a, const int &b)  
  28. {  
  29.       return P[step-1][a] < P[step-1][b];  
  30. }  
  31.   
  32. inline void suffixArray(const string &s)  
  33. {  
  34.       int len = s.size();  
  35.       for (int i = 0; i < len; i++) P[0][i] = s[i] - 'a';  
  36.       step = 1;  
  37.       int cnt = 1;  
  38.       for ( ; cnt>>1 < len; step++, cnt <<= 1)  
  39.       {  
  40.             for (int i = 0; i < len; i++)  
  41.             {  
  42.                   L[i].first = P[step-1][i];  
  43.                   L[i].second = (i + cnt) < len ? P[step-1][i+cnt] : -1;  
  44.                   L[i].p = i;  
  45.             }  
  46.             sort(L, L+len);  
  47.             for (int i = 0; i < len; i++)  
  48.             {  
  49.                   if (i > 0 && L[i].first == L[i-1].first && L[i].second == L[i-1].second)  
  50.                         P[step][ L[i].p ] = P[step][ L[i-1].p ];  
  51.                   else  
  52.                         P[step][ L[i].p ] = i;  
  53.             }  
  54.       }  
  55.       for (int i = 0; i < len; i++) B[i] = i;  
  56.       sort(B, B+len, comp2);  
  57. }  
  58.   
  59. inline void LCP(const string &s)  
  60. {  
  61.       int len = s.size();  
  62.       memset(lcp, 0, sizeof lcp);  
  63.       for (int i = 1; i < len; i++)  
  64.       {  
  65.             int x = B[i];  
  66.             int y = B[i-1];  
  67.             for (int k = step-1; k >= 0 && x < len && y < len; k--)  
  68.             {  
  69.                   if (P[k][x] == P[k][y])  
  70.                   {  
  71.                         lcp[i] += (1 << k);  
  72.                         x += (1 << k);  
  73.                         y += (1 << k);  
  74.                   }  
  75.             }  
  76.       }  
  77. }  
  78.   
  79. struct segmentTree  
  80. {  
  81.       int len, pos;  
  82.       segmentTree(int len = inf, int pos = 0) : len(len), pos(pos) {}  
  83.   
  84.       inline void assignLeaf(int l, int p)  
  85.       {  
  86.             len = l;  
  87.             pos = p;  
  88.       }  
  89.       inline void marge(const segmentTree &lft, const segmentTree &rgt)  
  90.       {  
  91.             len = min(lft.len, rgt.len);  
  92.             pos = max(lft.pos, rgt.pos);  
  93.       }  
  94. } Tree[maxn << 2];  
  95.   
  96. inline void build(int node, int a, int b)  
  97. {  
  98.       if (a == b)  
  99.       {  
  100.             Tree[node].assignLeaf(lcp[a], B[a]);  
  101.             return;  
  102.       }  
  103.       int lft = node << 1;  
  104.       int rgt = lft | 1;  
  105.       int mid = (a + b) >> 1;  
  106.       build(lft, a, mid);  
  107.       build(rgt, mid+1, b);  
  108.       Tree[node].marge(Tree[lft], Tree[rgt]);  
  109. }  
  110.   
  111. inline segmentTree query(int node, int a, int b, int i, int j)  
  112. {  
  113.       if (a == i && b == j) return Tree[node];  
  114.       int lft = node << 1;  
  115.       int rgt = lft | 1;  
  116.       int mid = (a + b) >> 1;  
  117.       segmentTree res = segmentTree();  
  118.       if (j <= mid)  
  119.       {  
  120.             segmentTree p = query(lft, a, mid, i, j);  
  121.             res.marge(res, p);  
  122.       }  
  123.       else if (i > mid)  
  124.       {  
  125.             segmentTree q = query(rgt, mid+1, b, i, j);  
  126.             res.marge(res, q);  
  127.       }  
  128.       else  
  129.       {  
  130.             segmentTree p = query(lft, a, mid, i, mid);  
  131.             segmentTree q = query(rgt, mid+1, b, mid+1, j);  
  132.             res.marge(res, p);  
  133.             res.marge(res, q);  
  134.       }  
  135.       return res;  
  136. }  
  137.   
  138. int main()  
  139. {  
  140.       FAST;  
  141.   
  142.       int m;  
  143.       while (cin >> m)  
  144.       {  
  145.             if (m == 0) break;  
  146.             string s;  
  147.             cin >> s;  
  148.             int len = s.size();  
  149.             if (m == 1)  
  150.             {  
  151.                   cout << len << " " << 0 << endl;  
  152.                   continue;  
  153.             }  
  154.             suffixArray(s);  
  155.             LCP(s);  
  156.             int maxlen = 0;  
  157.             int pos = 0;  
  158.   
  159.             build(1, 0, len-1);  
  160.   
  161.             for (int i = 1; i+m-2 < len; i++)  
  162.             {  
  163.                   if (i+m-2 < 0) continue;  
  164.                   segmentTree res = query(1, 0, len-1, i, i+m-2);  
  165.                   if (res.len > 0)  
  166.                   {  
  167.                         res.pos = max(res.pos, B[i-1]);  
  168.                         if (res.len > maxlen) maxlen = res.len, pos = res.pos;  
  169.                         else if (res.len == maxlen && res.pos > pos) pos = res.pos;  
  170.                   }  
  171.             }  
  172.             if (maxlen == 0) cout << "none" << endl;  
  173.             else cout << maxlen << " " << pos << endl;  
  174.       }  
  175. }  

No comments:

Post a Comment

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