0

For course I am taking I need to implement the Rabin-Karp string search algorithm, with different hash implementation. First I have done a rolling hash and that works just fine. Problem is when it comes to linear and separate chaining hash. I have made a linear hash header file and for primary hash methods it works Ok, also I have written a Rabin-Karp algorithm that works with other versions of hash. But now I do not know how to put this two together.

Here is what I have written by now hash.h

 #ifndef HASH_H
    #define HASH_H
    #include <vector>
    using namespace std;
    template <typename Tip>
    class Hash {
      struct Element {
        int key;
        Tip value;
        int mark; //0 free, 1 occupied, 2 was occupied

        Element(int key = 0, Tip value = Tip(), int mark = 1):key(key),value(value),mark(mark){}
      };
      int h1(int key) {
        return key%capacity;
      }
      int h2(int key) {
        return 2*(key%5) + 1;
      }
      int capacity;
      int no_of_elements;
      const double factor_of_full;
      vector<Element> Tabel;
      public:
      Hash():capacity(128),no_of_elements(0),factor_of_full(0.5){
              Tabel.resize(capacity);
              for(int i=0;i<capacity;i++)
                Tabel[i].mark = 0;
      }
      void Insert(pair<int,Tip> element);
      Tip Find(int key);
      void Delete(int key);
    };

    template <typename Tip>
    void Hash<Tip>::Insert(pair<int,Tip> element) {
      if((double(no_of_elements+1))/capacity>factor_of_full) {
        vector<Element> coppy = Tabel;
        capacity*=2;
        Tabel.resize(capacity);
        no_of_elements = 0;
        for(int i=0;i<Tabel.size();i++)
            Tabel[i].mark = 0;
        for(int i=0;i<coppy.size();i++)
            if(coppy[i].mark == 1)
              Insert({coppy[i].key,coppy[i].value});

      }

      int index = h1(element.first);
      while(Tabel[index].mark == 1)
        index = (index + h2(element.first))%capacity;
      Tabel[index] = Element(element.first,element.second);
      no_of_elements++;
    }

    template <typename Tip>
    Tip Hash<Tip>::Find(int key) {
      int index = h1(key);
      for(int i=0;i<capacity;i++) {
        if(Tabel[index].mark == 0)
          break;
        if(Tabel[index].mark == 1 && Tabel[index].key == key)
          return Tabel[index].value;
        else index = (index+h2(key))%capacity;
      }
      return Tip();
    }

    template <typename Tip>
    void Hash<Tip>::Delete(int key) {
      int index = h1(key);
      for(int i=0;i<capacity;i++) {
        if(Tabel[index].mark == 0)
          return;
        if(Tabel[index].mark == 1 && Tabel[index].key == key) {
          Tabel[index].mark = 2;
          no_of_elements--;
        }
        else index = (index+h2(key))%capacity;
      }
      return;
    }
    #endif // HASH_H

Rabin_Karp.cpp

#include <bits/stdc++.h>

#include "hash.h"
using namespace std;

const int P_B= 227;
const int P_M = 1000005;


int rabin_karp(const string& n, const string& find) {

   int h1 = Hash(n);
   int h2 = 0;
   int pow = 1;
   for (int i = 0; i < n.size(); i++)
      pow = (pow * P_B) % P_M;
   for (int i = 0; i < find.size(); i++) {
      h2 = h2*P_B + find[i];
      h2 %= P_M;
      if (i >= n.size()) {
         h2 -= pow * find[i-n.size()] % P_M;
         if (h2 < 0)
            h2 += P_M;
      }
      if (i >= n.size()-1 && h1 == h2)
         return i - (n.size()-1);
   }
   return -1;
}
DiN
  • 7
  • 4
  • `#include ` -- [Don't do this](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – PaulMcKenzie Feb 14 '20 at 20:45
  • Unrelated: `using namespace std;` is a dangerous thing to place in a header. If you want the deal with the mess it can cause, that's on you, but when you put it in a header, you risk blowing up other people's code. – user4581301 Feb 14 '20 at 20:51
  • If the interfaces are the same, you could make `rabin_karp` a template function and specify which hash to use as a template argument. – user4581301 Feb 14 '20 at 20:53
  • @PaulMcKenzie it is only the scratch version, when I make it works I'll change that. At this moment I have a lot of struggle with putting this two together. I think that I need a function Hash(n) /* that is problem I think */ that I have no Idea how and where to put in. – DiN Feb 14 '20 at 20:59
  • @user4581301 what do you have on mind by "specify which hash to use as a template argument", to do something like template void Hash::Hash( "What I would take as parameter, I need a string but how to take it, ad type maybe?") {... return ("what would I need to return here") – DiN Feb 14 '20 at 21:13
  • I may have misread your question. You have one `rabin_karp` function and many possible hash functions. I was thinking `rabin_karp` is the template function and the template argument is one of the many hash functions that could be used by `rabin_karp`. – user4581301 Feb 14 '20 at 21:13
  • @user4581301 I was thinking to do hash as it needs to be with all of it's functions that has to have by definition. Using that hash I want to make in .cpp file Rabin Karp algorithm. This far is all good but now I can't put this two together, they are working separate. // I think I am missing one function and have no idea how it needs to look like – DiN Feb 14 '20 at 21:17

0 Answers0