Showing posts with label Aho-Corasick Algorithm. Show all posts
Showing posts with label Aho-Corasick Algorithm. Show all posts

Saturday, June 1, 2019

[Codeforces] D. Frequency of String

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : D. Frequency of String
Source            : Codeforces
Category          : Data Structure, String
Algorithm         : Aho Corasick Algorithm
Verdict           : Accepted

  1. #include <bits/stdc++.h>  
  2.   
  3. using namespace std;  
  4.   
  5. #define memo(a, b)                      memset(a, b, sizeof a)  
  6.   
  7. static const int maxn = 5e5 + 5;  
  8.   
  9. int Next[27][maxn], End[maxn], sz, Num[maxn], backPoint[maxn];  
  10. bool created[maxn];  
  11. vector <int> out[maxn], patternIndices[maxn], occur[maxn];  
  12.   
  13. string text, pattern[maxn];  
  14. int numPat, k[maxn];  
  15.   
  16.   
  17. void init()  
  18. {  
  19.       sz = 0;  
  20.       memo(Next, 0);  
  21.       memo(created, 0);  
  22.       memo(Num, 0);  
  23.       for (int i = 0; i < maxn; i++)  
  24.       {  
  25.             out[i].clear();  
  26.             patternIndices[i].clear();  
  27.       }  
  28. }  
  29.   
  30. void insertPattern(const string &pat, const int id)  
  31. {  
  32.       int v = 0;  
  33.       for (char ch : pat)  
  34.       {  
  35.             int val = ch - 'a';  
  36.             if (!created[ Next[val][v] ])  
  37.             {  
  38.                   ++sz;  
  39.                   Next[val][v] = sz;  
  40.                   created[sz] = 1;  
  41.             }  
  42.             v = Next[val][v];  
  43.       }  
  44.       patternIndices[v].emplace_back(id);  
  45. }  
  46.   
  47. void findBackPointer() // Build Failure Function  
  48. {  
  49.       queue <int> PQ;  
  50.       int v = 0;  
  51.       for (int i = 0; i < 26; i++)  
  52.       {  
  53.             if (Next[i][v])  
  54.             {  
  55.                   PQ.emplace(Next[i][v]);  
  56.                   backPoint[ Next[i][v] ] = v;  
  57.                   out[v].emplace_back(Next[i][v]);  
  58.             }  
  59.       }  
  60.       while (!PQ.empty())  
  61.       {  
  62.             int u = PQ.front(); PQ.pop();  
  63.             for (int i = 0; i < 26; i++)  
  64.             {  
  65.                   int v = Next[i][u];  
  66.                   if (!v) continue;  
  67.                   int w = backPoint[u];  
  68.                   while (w && Next[i][w] == 0) w = backPoint[w];  
  69.                   backPoint[v] = Next[i][w];  
  70.                   out[ Next[i][w] ].push_back(v);  
  71.                   for (int p : patternIndices[ Next[i][w] ]) patternIndices[v].push_back(p);  
  72.                   PQ.emplace(v);  
  73.             }  
  74.       }  
  75. }  
  76.   
  77. void insertText(const string &text)  
  78. {  
  79.       int v = 0;  
  80.       for (int i = 0; i < text.size(); i++)  
  81.       {  
  82.             int val = text[i] - 'a';  
  83.             while (v && Next[val][v] == 0) v = backPoint[v];  
  84.             v = Next[val][v];  
  85.             for (int p : patternIndices[v]) occur[p].push_back(i);  
  86.       }  
  87. }  
  88.   
  89. int query(int id)  
  90. {  
  91.       int len = pattern[id].size();  
  92.       int occ = occur[id].size();  
  93.       if (occ < k[id]) return -1;  
  94.       int mini = 1e7;  
  95.       for (int i = 0, j = k[id] - 1; j < occ; i++, j++) mini = min(mini, occur[id][j] - occur[id][i]);  
  96.       return mini + len;  
  97. }  
  98.   
  99. signed main()  
  100. {  
  101.       ios_base::sync_with_stdio(false);  
  102.       cin.tie(nullptr);  
  103.       cout.tie(nullptr);  
  104.       cout << fixed << setprecision(3);  
  105.   
  106.       #ifndef ONLINE_JUDGE  
  107.             freopen("in.txt", "r", stdin);  
  108.       #endif // ONLINE_JUDGE  
  109.   
  110.       init();  
  111.   
  112.       cin >> text >> numPat;  
  113.       for (int i = 1; i <= numPat; i++)  
  114.       {  
  115.             cin >> k[i] >> pattern[i];  
  116.             insertPattern(pattern[i], i);  
  117.       }  
  118.       findBackPointer();  
  119.       insertText(text);  
  120.       for (int i = 1; i <= numPat; i++) cout << query(i) << '\n';  
  121. }  


Monday, January 7, 2019

[CodeChef] Music & Lyrics

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Music & Lyrics
Source            : CodeChef
Category          : String
Algorithm         : Aho-Corasick Algorithm
Verdict           : Accepted
#include <bits/stdc++.h>
 
using namespace std;
 
const int mxPat = 5000 + 5;
const int mxText = 50000 + 5;
 
struct node
{
      int cnt;
      bool vis;
      node* next[200];
      vector <node *> bpin;
      node()
      {
            cnt = 0;
            vis = false;
            for (int i = 0; i < 200; i++) next[i] = NULL;
            bpin.clear();
    }
    ~node()
    {
          for (int i = 1; i < 200; i++)
          {
                if (next[i] && next[i] != this) delete next[i];
          }
    }
}*root;
 
inline void buildTrie(char dictionary[][mxPat], int n)
{
      // dictionary[][] = all query word
      // n              = total query word
      root = new node();
      // usual trie tree
      for (int i = 0; i < n; i++)
      {
            node* curr = root;
            for (int j = 0; dictionary[i][j]; j++)
            {
                  int val = dictionary[i][j] - '0' + 10;
                  if (curr->next[val] == NULL) curr->next[val] = new node();
                  curr = curr->next[val];
            }
      }
      // Pushing adjacent node to root into queue
      queue <node *> PQ;
      for (int i = 0; i < 200; i++)
      {
            if (root->next[i] == NULL)
            {
                  root->next[i] = root;
            }
            else
            {
                  PQ.push(root->next[i]);
                  root->next[i]->next[0] = root;  // ->next[0] = back pointer
            }
      }
      //Building Aho - Corasik tree
      while (!PQ.empty())
      {
            node* u = PQ.front();   // parent node
            PQ.pop();
            for (int i = 1; i < 200; i++)
            {
                  if (u->next[i])
                  {
                        node* v = u->next[i];   // child node
                        node* w = u->next[0];   // back pointer of parent node
                        while (!w->next[i])     // untill the char (i - 'a' + 1) child is not found
                              w = w->next[0];
                        v->next[0] = w = w->next[i];  // back pointer of v will be found child above
                        w->bpin.push_back(v);    // bpin will be used in dfs
                                                // here w is the new found match node
                        PQ.push(v);
                  }
            }
      }
}
 
// Third step processing the text
void aho_corasik(char word[][mxText], int n)
{
      //node* p = root;
      for (int i=0; i<n; i++)
      {
            node* p = root;
            for (int j = 0; word[i][j]; j++)
            {
                  //if (word[i][j] == '-')
                  //    continue;
 
                  int id = word[i][j] - '0' + 10;
                  while (!p->next[id])
                        p = p->next[0];
                  p = p->next[id];
                  p->cnt++;
            }
      }
}
 
// DFS for counting
int dfs(node* p)
{
      if (p->vis) return p->cnt;
      p->vis = true;
      for (int i = 0; i < (int)p->bpin.size(); i++)
            p->cnt += dfs(p->bpin[i]);
      return p->cnt;
}
 
char word[105][mxText];
char dictionary[505][mxPat];
 
int main()
{
      //freopen("in.txt", "r", stdin);
 
      int pat;
      scanf("%d", &pat);
      for (int i = 0; i < pat; i++)
            scanf("%s", dictionary[i]);
      buildTrie(dictionary, pat);
      int text;
      scanf("%d", &text);
      for (int t = 0; t < text; t++)
            scanf("%s", word[t]);
      aho_corasik(word, text);
      for (int i = 0; i < pat; i++)
      {
            node* p = root;
            for (int j = 0; dictionary[i][j]; j++)
            {
                  int id = dictionary[i][j] - '0' + 10;
                  if (p->next[id]) p = p->next[id];
            }
            printf("%d\n", dfs(p));
      }
      delete root;
      return 0;
}
 
 
 
/*************************************************
>>>>>> Input - 1
 
5
he
she
sher
his
hers
2
ushers
she-said-he-said-she-said-he-said-his
 
>>>>>> Output - 1
5
3
1
1
1
 
>>>>>> Input - 2
 
3
who
shawty
hawt
2
Get-it-shawty-Get-it-shawty
Whoa-W-W-Whoa-Shawtyyyyy
 
>>>>> Output - 2
 
0
2
3
 
***********************************************/