Monday, December 17, 2018

[toph.co] Distinctness

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Distinctness
Source            : toph.co
Category          : String
Algorithm         : Suffix Automata
Verdict           : Accepted
#include "bits/stdc++.h"
 
using namespace std;
 
#define FAST           ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
 
#define vi             vector <int>
#define eb             emplace_back
#define sze(a)         (int)a.size()
#define ll             long long
 
static const int maxn = 1e5 + 5;
 
string A;
 
struct state
{
      int len, link;
      map <char, int> next;
};
 
state st[maxn << 1];
int sz, last;
 
inline void init()
{
      sz = last = 0;
      st[0].len = 0;
      st[0].link = -1;
      st[0].next.clear();
      ++sz;
      for (int i = 1; i < (maxn << 1); i++)
      {
            st[i].len = 0;
            st[i].link = 0;
            st[i].next.clear();
      }
}
 
inline ll sz_extend(char c)
{
      ll sum = 0;
      int cur = sz++;
      st[cur].len = st[last].len + 1;
      int p;
      for (p = last; p != -1 && !st[p].next.count(c); p = st[p].link)
      {
            st[p].next[c] = cur;
      }
      if (p == -1)
      {
            st[cur].link = 0;
      }
      else
      {
            int q = st[p].next[c];
            if (st[p].len + 1 == st[q].len)
            {
                  st[cur].link = q;
            }
            else
            {
                  int clone = sz++;
                  st[clone].len = st[p].len + 1;
                  st[clone].next = st[q].next;
                  st[clone].link = st[q].link;
 
                  for ( ; p != -1 && st[p].next[c] == q; p = st[p].link)
                  {
                        st[p].next[c] = clone;
                  }
                  sum = sum - (st[q].len - st[ st[q].link ].len);
                  st[q].link = st[cur].link = clone;
                  sum = sum + st[q].len - st[ st[q].link ].len;
                  sum = sum + st[clone].len - st[ st[clone].link ].len;
            }
      }
      sum = sum + st[cur].len - st[ st[cur].link ].len;
      last = cur;
      return sum;
}
 
int main()
{
      FAST;
 
      init();
 
      cin >> A;
      ll tsub = 0;
      for (char ch : A)
      {
            tsub += sz_extend(ch);
            cout << tsub << endl;
      }
}
 

[toph.co] Another Dirty String

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Another Dirty String
Source            : toph.co
Category          : String, Data Structure
Algorithm         : Suffix Automata, KMP, Segment Tree
Verdict           : Accepted
#include "bits/stdc++.h"
 
using namespace std;
 
#define FAST       ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
 
#define vi         vector <int>
#define eb         emplace_back
#define sze(a)      (int)a.size()
 
static const int maxn = 1e5 + 5;
 
string A, B, C;
int occ[maxn], cumocc[maxn];
 
inline vi longestPreffixSuffix(string pat)
{
      vi lps;
      lps.eb(0);
      int i = 1, j = 0;
      int len = sze(pat);
      while (i < len)
      {
            if (pat[i] == pat[j])
            {
                  i++;
                  j++;
                  lps.eb(j);
            }
            else
            {
                  if (j)
                  {
                        j = lps[j-1];
                  }
                  else
                  {
                        i++;
                        lps.eb(0);
                  }
            }
      }
      return lps;
}
 
inline void kmp(string text, string pat)
{
      int lenText = sze(text);
      int lenPat = sze(pat);
      vi lps = longestPreffixSuffix(pat);
      int i = 0, j = 0;
      while (i < lenText)
      {
            if (text[i] == pat[j])
            {
                  i++;
                  j++;
            }
            if (j == lenPat)
            {
                  occ[i-1-lenPat+1] = 1;
                  j = lps[j-1];
            }
            else if (i < lenText && text[i] != pat[j])
            {
                  if (j) j = lps[j-1];
                  else i++;
            }
      }
}
 
struct segmentTree
{
      int lastocc;
      void assignLeaf(int val, int pos)
      {
            lastocc = -1;
            if (val == 1) lastocc = pos;
      }
      void marge(segmentTree l, segmentTree r)
      {
            if (l.lastocc > r.lastocc) lastocc = l.lastocc;
            else if (l.lastocc < r.lastocc) lastocc = r.lastocc;
            else lastocc = l.lastocc;
      }
} tree[maxn << 2];
 
inline void build(int node, int a, int b)
{
      if (a == b)
      {
            tree[node].assignLeaf(occ[a], a);
            return;
      }
      int lft = node << 1;
      int rgt = lft | 1;
      int mid = (a + b) >> 1;
      build(lft, a, mid);
      build(rgt, mid+1, b);
      tree[node].marge(tree[lft], tree[rgt]);
}
 
inline segmentTree query(int node, int a, int b, int i, int j)
{
      if (a > b || a > j || b < i)
      {
            segmentTree nul;
            nul.lastocc = -1;
            return nul;
      }
      if (a >= i && b <= j) return tree[node];
      int lft = node << 1;
      int rgt = lft | 1;
      int mid = (a + b) >> 1;
      segmentTree p, q, res;
      p = query(lft, a, mid, i, j);
      q = query(rgt, mid+1, b, i, j);
      res.marge(p, q);
      return res;
}
 
struct state
{
      int len, link;
      map <char, int> next;
};
 
state st[maxn << 1];
 
int sz, last;
 
inline void init()
{
      sz = last = 0;
      st[0].len = 0;
      st[0].link = -1;
      st[0].next.clear();
      ++sz;
      for (int i = 1; i < (maxn << 1); i++)
      {
            st[i].len = 0;
            st[i].link = 0;
            st[i].next.clear();
      }
}
 
inline void sz_extend(char c)
{
      int cur = sz++;
      st[cur].len = st[last].len + 1;
      int p;
      for (p = last; p != -1 && !st[p].next.count(c); p = st[p].link)
      {
            st[p].next[c] = cur;
      }
      if (p == -1)
      {
            st[cur].link = 0;
      }
      else
      {
            int q = st[p].next[c];
            if (st[p].len + 1 == st[q].len)
            {
                  st[cur].link = q;
            }
            else
            {
                  int clone = sz++;
                  st[clone].len = st[p].len + 1;
                  st[clone].next = st[q].next;
                  st[clone].link = st[q].link;
 
                  for ( ; p != -1 && st[p].next[c] == q; p = st[p].link)
                  {
                        st[p].next[c] = clone;
                  }
                  st[q].link = st[cur].link = clone;
            }
      }
      last = cur;
}
 
 
inline int LCS(string A, string B, string C)
{
      int lenA = sze(A);
      int lenB = sze(B);
      int lenC = sze(C);
 
      memset(occ, 0, sizeof occ);
      memset(cumocc, 0, sizeof cumocc);
      memset(tree, -1, sizeof tree);
 
      kmp(B, C);
 
      build(1, 0, lenB-1);
 
      init();
      for (int i = 0; i < lenA; i++) sz_extend(A[i]);
 
      int v = 0;
      int l = 0;
      int best = 0;
      int bestPos = 0;
 
      for (int i = 0; i < lenB; i++)
      {
            while (v && !st[v].next.count(B[i]))
            {
                  v = st[v].link;
                  l = st[v].len;
            }
            if (st[v].next.count(B[i]))
            {
                  v = st[v].next[ B[i] ];
                  l++;
            }
 
            int newl = 0;
            if (l < lenC)
            {
                  newl = l;
            }
            else
            {
                  int bgn = i - l + 1;
                  int edd = i - lenC + 1;
                  segmentTree q = query(1, 0, lenB-1, bgn, edd);
                  if (q.lastocc == -1)
                  {
                        newl = l;
                  }
                  else
                  {
                        newl = i - q.lastocc;
                  }
            }
            if (newl > best)
            {
                  best = newl;
                  bestPos = i;
            }
      }
//      cout << B.substr(bestPos - best + 1, best) << endl;
      return best;
}
 
int main()
{
      //freopen("in.txt", "r", stdin);
      FAST;
 
      int tc;
      cin >> tc;
      for (int tcase = 1; tcase <= tc; tcase++)
      {
            cin >> A >> B >> C;
            cout << LCS(A, B, C) << endl;
      }
}
 
 

Saturday, December 15, 2018

/**
 * Author      : Dipu Kumar Mohanto
 *               CSE, BRUR.
 * Problem     : D. Closest Equals
 * Category    : Data Structures Variations
 * 
 * Verdict     : Accepted
**/
Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : DCP-60: Holloween Party
Source            : Devskill
Category          : Graph Theory
Algorithm         : Sorting Queries
Verdict           : Accepted
  #include "bits/stdc++.h"   using namespace std;   static const int maxn = 6e5 + 5; static const int inf = 1e7 + 7;   struct node { int l, p; node(int l = 0, int p = 0) : l(l), p(p) {} };   int arr[maxn]; map <int, int> mapper; vector <node> allquery[maxn]; int ans[maxn]; int n, q;   int tree[maxn << 2];   inline void update(int node, int a, int b, int pos, int val) { if (a > b || a > pos || b < pos) return; if (a >= pos && b <= pos) { tree[node] = min(tree[node], val); return; } int lft = node << 1; int rgt = lft | 1; int mid = (a + b) >> 1; update(lft, a, mid, pos, val); update(rgt, mid+1, b, pos, val); tree[node] = min(tree[lft], tree[rgt]); }   inline int query(int node, int a, int b, int i, int j) { if (a > b || a > j || b < i) return inf; if (a >= i && b <= j) return tree[node]; int lft = node << 1; int rgt = lft | 1; int mid = (a + b) >> 1; int p = query(lft, a, mid, i, j); int q = query(rgt, mid + 1, b, i, j); return min(p, q); }   int main() { scanf("%d %d", &n, &q); for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); for (int i = 1; i <= q; i++) { int l, r; scanf("%d %d", &l, &r); allquery[r].emplace_back(l, i); } fill(begin(tree), end(tree), inf); for (int i = 1; i <= n; i++) { if (mapper.find(arr[i]) != mapper.end()) { int pos = mapper[ arr[i] ]; int val = i - pos; update(1, 1, n, pos, val); } mapper[ arr[i] ] = i; for (node it : allquery[i]) ans[it.p] = query(1, 1, n, it.l, i); } for (int i = 1; i <= q; i++) printf("%d\n", ans[i] == inf ? -1 : ans[i]); }