Saturday, November 23, 2019

[Toph] Simple As a Substring!

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Simple As a Substring!
Source            : Toph
Category          : String
Algorithm         : Suffix Tree
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. static const int maxn = 5e6 + 5;  
  6. static const int inf  = 1e9 + 5;  
  7.   
  8. struct Node  
  9. {  
  10.       int l;  
  11.       int r;  
  12.       int par;  
  13.       int link;  
  14.       map <char,int> next;  
  15.       Node(int l = 0, int r = 0, int par = -1)  
  16.             : l(l)  
  17.             , r(r)  
  18.             , par(par)  
  19.             , link(-1) {}  
  20.   
  21.       int len()  
  22.       {  
  23.             return r - l;  
  24.       }  
  25.       int &get(char c)  
  26.       {  
  27.             if (!next.count(c)) next[c] = -1;  
  28.             return next[c];  
  29.       }  
  30. };  
  31.   
  32. Node t[maxn];  
  33. string s;  
  34. int sz;  
  35. int n;  
  36.   
  37. struct state  
  38. {  
  39.       int v, pos;  
  40.       state(int v, int pos) : v(v), pos(pos) {}  
  41. };  
  42.   
  43. state ptr (0, 0);  
  44.   
  45. state go(state st, int l, int r)  
  46. {  
  47.       while (l < r)  
  48.       {  
  49.             if (st.pos == t[st.v].len())  
  50.             {  
  51.                   st = state (t[st.v].get( s[l] ), 0);  
  52.                   if (st.v == -1) return st;  
  53.             }  
  54.             else  
  55.             {  
  56.                   if (s[ t[st.v].l + st.pos ] != s[l])  
  57.                         return state (-1, -1);  
  58.                   if (r - l < t[st.v].len() - st.pos)  
  59.                         return state (st.v, st.pos + r-l);  
  60.                   l += t[st.v].len() - st.pos;  
  61.                   st.pos = t[st.v].len();  
  62.             }  
  63.       }  
  64.       return st;  
  65. }  
  66.   
  67. int split(state st)  
  68. {  
  69.       if (st.pos == t[st.v].len())  
  70.             return st.v;  
  71.       if (st.pos == 0)  
  72.             return t[st.v].par;  
  73.       Node v = t[st.v];  
  74.       int id = sz++;  
  75.       t[id] = Node(v.l, v.l + st.pos, v.par);  
  76.       t[v.par].get(s[v.l]) = id;  
  77.       t[id].get(s[v.l + st.pos]) = st.v;  
  78.       t[st.v].par = id;  
  79.       t[st.v].l += st.pos;  
  80.       return id;  
  81. }  
  82.   
  83. int get_link(int v)  
  84. {  
  85.       if (t[v].link != -1)  
  86.             return t[v].link;  
  87.       if (t[v].par == -1)  
  88.             return 0;  
  89.       int to = get_link(t[v].par);  
  90.       return t[v].link = split(go(state(to, t[to].len()), t[v].l + (t[v].par == 0), t[v].r));  
  91. }  
  92.   
  93. void tree_extend(int pos)  
  94. {  
  95.       for(;;)  
  96.       {  
  97.             state nptr = go(ptr, pos, pos+1);  
  98.             if (nptr.v != -1)  
  99.             {  
  100.                   ptr = nptr;  
  101.                   return;  
  102.             }  
  103.             int mid = split(ptr);  
  104.             int leaf = sz++;  
  105.             t[leaf] = Node(pos, n, mid);  
  106.             t[mid].get(s[pos]) = leaf;  
  107.             ptr.v = get_link(mid);  
  108.             ptr.pos = t[ptr.v].len();  
  109.             if (!mid) break;  
  110.       }  
  111. }  
  112.   
  113. void build_tree()  
  114. {  
  115.       sz = 1;  
  116.       for (int i = 0; i < n; i++) tree_extend(i);  
  117. }  
  118.   
  119. int mark[maxn];  
  120. int counter[maxn][11];  
  121. int numstr;  
  122.   
  123. void dfs(int u = 0)  
  124. {  
  125.       if (t[u].r == n)  
  126.       {  
  127.             counter[u][ mark[ t[u].l ] ]++;  
  128.             return;  
  129.       }  
  130.       for (auto it : t[u].next)  
  131.       {  
  132.             int v = it.second;  
  133.             dfs(v);  
  134.             for (int i = 0; i < numstr; i++) counter[u][i] += counter[v][i];  
  135.       }  
  136. }  
  137.   
  138. int solve(int u = 0)  
  139. {  
  140.       int one = 0;  
  141.       for (int i = 0; i < numstr; i++)  
  142.       {  
  143.             if (counter[u][i] == 0) return -inf;  
  144.             if (counter[u][i] == 1) ++one;  
  145.       }  
  146.       if (one == numstr) return t[u].len();  
  147.       int maxi = -inf;  
  148.       for (auto it : t[u].next)  
  149.       {  
  150.             int v = it.second;  
  151.             int go = t[u].len() + solve(v);  
  152.             if (go > maxi) maxi = go;  
  153.       }  
  154.       return maxi;  
  155. }  
  156.   
  157.   
  158. signed main()  
  159. {  
  160.       ios_base::sync_with_stdio(false);  
  161.       cin.tie(nullptr);  
  162.       cout.tie(nullptr);  
  163.   
  164.       #ifndef ONLINE_JUDGE  
  165.             freopen("in.txt""r", stdin);  
  166.       #endif // ONLINE_JUDGE  
  167.   
  168.       cin >> numstr;  
  169.       char asign = 'A';  
  170.       for (int i = 1; i <= numstr; i++)  
  171.       {  
  172.             string str;  
  173.             cin >> str;  
  174.             s += str;  
  175.             if (i < numstr) s += asign;  
  176.             asign++;  
  177.       }  
  178.       s += '$';  
  179.       n = s.size();  
  180.       int v = 0;  
  181.       for (int i = 0; i < n; i++)  
  182.       {  
  183.             mark[i] = v;  
  184.             if (!islower(s[i])) v++;  
  185.       }  
  186.       build_tree();  
  187.       dfs();  
  188.       cout << max(0, solve());  
  189. }  

No comments:

Post a Comment

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