Tuesday, August 25, 2020

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Strange Substring
Source            : CS Academy
Category          : String, Data Structure
Algorithm         : Suffix Tree
Verdict           : Accepted
You are given two strings A and B, consisting only of lowercase letters from the English alphabet. Count the number of distinct strings S, which are substrings of A, but not substrings of B.

 

  1. #pragma once  
  2. #undef _GLIBCXX_DEBUG  
  3.   
  4. #include "bits/stdc++.h"  
  5. #include "ext/pb_ds/assoc_container.hpp"  
  6. #include "ext/pb_ds/tree_policy.hpp"  
  7. #include "ext/rope"  
  8.   
  9. using namespace std;  
  10. using namespace __gnu_pbds;  
  11. using namespace __gnu_cxx;  
  12.   
  13. void trace(int x)                         { cerr << x; }  
  14. void trace(long x)                        { cerr << x; }  
  15. void trace(long long x)                   { cerr << x; }  
  16. void trace(unsigned x)                    { cerr << x; }  
  17. void trace(unsigned long x)               { cerr << x; }  
  18. void trace(unsigned long long x)          { cerr << x; }  
  19. void trace(float x)                       { cerr << x; }  
  20. void trace(double x)                      { cerr << x; }  
  21. void trace(long double x)                 { cerr << x; }  
  22. void trace(char x)                        { cerr << '\'' << x << '\''; }  
  23. void trace(const char *x)                 { cerr << '\"' << x << '\"'; }  
  24. void trace(const string &x)               { cerr << '\"' << x << '\"'; }  
  25. void trace(bool x)                        { cerr << (x ? "true" : "false"); }  
  26.   
  27. template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }  
  28. template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }  
  29. template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }  
  30. template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }  
  31. template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }  
  32. void _print()                                                                                      { cerr << "]\n"; }  
  33. template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }  
  34.   
  35. #ifndef ONLINE_JUDGE  
  36.       #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)  
  37. #else  
  38.       #define debug(x...)  
  39. #endif // ONLINE_JUDGE  
  40.   
  41. template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;  
  42. template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;  
  43.   
  44. template <typename T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }  
  45. template <typename T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }  
  46. template <typename T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }  
  47.   
  48. template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }  
  49. template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }  
  50.   
  51. mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());  
  52.   
  53. #define ll              long long int  
  54. #define ull             unsigned long long int  
  55. #define ld              long double  
  56. #define endl            '\n'  
  57. #define pii             pair <int, int>  
  58. #define pll             pair <ll, ll>  
  59. #define mk              make_pair  
  60. #define ff              first  
  61. #define ss              second  
  62. #define all(a)          (a).begin(), (a).end()  
  63. #define rall(a)         (a).rbegin(), (a).rend()  
  64. #define eb              emplace_back  
  65. #define pb              push_back  
  66. #define pf              push_front  
  67. #define allUpper(a)     transform(all(a), a.begin(), :: toupper)  
  68. #define allLower(a)     transform(all(a), a.begin(), :: tolower)  
  69. #define LINE            cerr << __LINE__ << " ";  
  70. #define memo(a, b)      memset(a, b, sizeof a)  
  71. #define sz(a)           (int)(a.size())  
  72. #define ook             order_of_key             // The number of items in a set that are strictly smaller than k  
  73. #define fbo             find_by_order            // It returns an iterator to the i'th largest element  
  74. #define ATCODER         if (fopen("in.txt", "r")) { freopen("in.txt", "r", stdin); }  
  75.   
  76. #define int             long long int  
  77.   
  78. const int maxn = 2e5 + 5;  
  79. const int logn = 19;  
  80. const long long MOD = 1e9 + 7;  
  81. const long long INF = 1e18;  
  82.   
  83. /* 
  84.       Algorithm : Suffix Tree 
  85.       Tutorial  : https://cp-algorithms.com/string/suffix-tree-ukkonen.html 
  86.                   https://www.geeksforgeeks.org/ukkonens-suffix-tree-construction-part-1/?ref=lbp 
  87.                   https://codeforces.com/blog/entry/16780 
  88.  
  89.       Visualization : https://brenden.github.io/ukkonen-animation/ 
  90.  
  91.       Structure Details : 
  92.                               Root = 0 
  93.                               l    = starting index of the substring 
  94.                               r    = ending index of the substring + 1 
  95.  
  96.       Problem   : https://codeforces.com/contest/427/problem/D 
  97.       Statement : Given two strings s1 and s2 consist of lowercase Latin letters, find the smallest (by length) 
  98.                   common substring p of both s1 and s2, where p is a unique substring in s1 and also in s2. 
  99.  
  100. */  
  101.   
  102. struct SuffixTree {  
  103.       struct Node {  
  104.             int l;  
  105.             int r;  
  106.             int par;  
  107.             int link;  
  108.             map <charint> child;  
  109.             Node(int l = 0, int r = 0, int par = -1)  
  110.                   : l(l), r(r), par(par), link(-1) {  
  111.                         child.clear();  
  112.                   }  
  113.   
  114.             void clean() {  
  115.                   l = 0;  
  116.                   r = 0;  
  117.                   par = -1;  
  118.                   link = -1;  
  119.                   child.clear();  
  120.             }  
  121.             int len() {  
  122.                   return r - l;  
  123.             }  
  124.             int &get(char c) {  
  125.                   if (child.count(c) == 0) {  
  126.                         child[c] = -1;  
  127.                   }  
  128.                   return child[c];  
  129.             }  
  130.       };  
  131.   
  132.       struct State {  
  133.             int v;  
  134.             int pos;  
  135.             State() {}  
  136.             State(int v, int pos)  
  137.                   : v(v), pos(pos) {}  
  138.       };  
  139.   
  140.       string s;  
  141.       int n;  
  142.       int SZ;  
  143.       vector <Node> stree;  
  144.       State ptr;  
  145.   
  146.       SuffixTree() {}  
  147.   
  148.       void init(string &str) {  
  149.             s = str;  
  150.             n = str.size();  
  151.             stree.clear(); stree.resize(4 * n + 5);  
  152.       }  
  153.       State go(State st, int l, int r) {  
  154.             while (l < r) {  
  155.                   if (st.pos == stree[st.v].len()) {  
  156.                         st = State(stree[st.v].get(s[l]), 0);  
  157.                         if (st.v == -1) {  
  158.                               return st;  
  159.                         }  
  160.                   }  
  161.                   else {  
  162.                         assert(stree[st.v].l + st.pos >= 0);  
  163.                         if (s[ stree[st.v].l + st.pos ] != s[l]) {  
  164.                               return State(-1, -1);  
  165.                         }  
  166.                         if (r - l < stree[st.v].len() - st.pos) {  
  167.                               return State(st.v, st.pos + r - l);  
  168.                         }  
  169.                         l += stree[st.v].len() - st.pos;  
  170.                         st.pos = stree[st.v].len();  
  171.                   }  
  172.             }  
  173.             return st;  
  174.       }  
  175.       int split(State st) {  
  176.             if (st.pos == stree[st.v].len()) {  
  177.                   return st.v;  
  178.             }  
  179.             if (st.pos == 0) {  
  180.                   return stree[st.v].par;  
  181.             }  
  182.             Node v = stree[st.v];  
  183.             int id = SZ++;  
  184.             stree[id] = Node(v.l, v.l + st.pos, v.par);  
  185.             stree[v.par].get(s[v.l]) = id;  
  186.             stree[id].get(s[v.l + st.pos]) = st.v;  
  187.             assert(st.v >= 0);  
  188.             stree[st.v].par = id;  
  189.             stree[st.v].l += st.pos;  
  190.             return id;  
  191.       }  
  192.       int get_link(int v) {  
  193.             if (stree[v].link != -1) {  
  194.                   return stree[v].link;  
  195.             }  
  196.             if (stree[v].par == -1) {  
  197.                   return 0;  
  198.             }  
  199.             int to = get_link(stree[v].par);  
  200.             return stree[v].link = split(go(State(to, stree[to].len()), stree[v].l + (stree[v].par == 0), stree[v].r));  
  201.       }  
  202.       void tree_extend(int pos) {  
  203.             for(;;) {  
  204.                   State nptr = go(ptr, pos, pos + 1);  
  205.                   if (nptr.v != -1) {  
  206.                         ptr = nptr;  
  207.                         return;  
  208.                   }  
  209.                   int mid = split(ptr);  
  210.                   int leaf = SZ++;  
  211.                   stree[leaf] = Node(pos, n, mid);  
  212.                   stree[mid].get(s[pos]) = leaf;  
  213.                   ptr.v = get_link(mid);  
  214.                   ptr.pos = stree[ptr.v].len();  
  215.                   if (!mid) {  
  216.                         break;  
  217.                   }  
  218.             }  
  219.       }  
  220.       void build_tree() {  
  221.             SZ = 1;  
  222.             ptr = {0, 0};  
  223.             for (int i = 0; i < stree.size(); i++) {  
  224.                         stree[i].clean();  
  225.             }  
  226.             for (int i = 0; i < n; i++) {  
  227.                   tree_extend(i);  
  228.             }  
  229.       }  
  230. };  
  231.   
  232. string s;  
  233. string t;  
  234. SuffixTree st;  
  235.   
  236. int dfs(int u = 0) {  
  237.       int sum = 0;  
  238.       for (auto it : st.stree[u].child) {  
  239.             char ch = it.ff;  
  240.             int v = it.ss;  
  241.             int l = st.stree[v].l;  
  242.             int r = st.stree[v].r - 1;  
  243.             debug(u, v, l, r);  
  244.             if (l > sz(t)) {  
  245.                   sum += st.stree[v].len();  
  246.             }  
  247.             sum += dfs(v);  
  248.       }  
  249.       return sum;  
  250. }  
  251.   
  252. signed main()  
  253. {  
  254.       ios_base::sync_with_stdio(false);  
  255.       cin.tie(nullptr); cout.tie(nullptr);  
  256.       cout.precision(12);  
  257.   
  258.       bool FILEIO = 1;  
  259.       if (FILEIO and fopen("in.txt""r")) {  
  260.             freopen("in.txt""r", stdin);  
  261.       }  
  262.   
  263.       cin >> s >> t;  
  264.       string str = t + "#" + s;  
  265.       st.init(str);  
  266.       st.build_tree();  
  267.       int ans = dfs();  
  268.       cout << ans << endl;  
  269. }  

No comments:

Post a Comment

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