N
N
Nikita2021-05-10 14:37:25
Algorithms
Nikita, 2021-05-10 14:37:25

Rabin-Karp algorithm. Where is the mistake?

Wrote a polynomial hash function without taking the remainder, can there be a mistake in this? The algorithm fails the second test.

Task:
Даны строки p и t. Требуется найти все вхождения строки p в строку t в качестве подстроки.
Формат входного файла
Первая строка входного файла содержит p, вторая t (1 <= |p|, |t| <= 10^6). Строки состоят из
букв латинского алфавита.
Формат выходного файла
В первой строке выведите количество вхождений строки p в строку t. Во второй строке выведите
в возрастающем порядке номера символов строки t, с которых начинаются вхождения p. Символы
нумеруются с единицы.


My decision:
#include <fstream>
#include <vector>
#include <string>

int x = 53;

int hash(const std::string& t, std::vector<int>& degree_x)
{
  int h = 0;
  for (int m = degree_x.size() - 2, i = 0; i < t.size(); m--, i++)
  {
    h += (t[i] - 'A' + 1) * degree_x[m];
  }
  return h;
}

bool equal(const std::string& t, const std::string& p)
{
  for (int i = 0; i < t.size(); i++)
  {
    if (t[i] != p[i])
      return false;
  }
  return true;
}

void buildH(std::string& t, std::string& p, std::vector<int>& H, std::vector<int>& degree_x)
{
  int n = t.size();
  int m = p.size();
  H[0] = hash(t.substr(0, m), degree_x);
  for (int i = 1; i < n - m + 1; i++)
  {
    H[i] = (H[i - 1] * x - (t[i - 1] - 'A' + 1) * degree_x.back() + (t[i + m - 1] - 'A' + 1));
  }
}

void Rabin_Karp(std::string& t, std::string& p, std::vector<int>& H, std::vector<int>& degree_x, std::vector<int>& answer)
{
  if (p.size() > t.size())
    return;
  buildH(t, p, H, degree_x);
  int hash_p = hash(p, degree_x);
  int n = t.size();
  int m = p.size();
  for (int i = 0; i < n - m + 1; i++)
  {
    if (H[i] != hash_p)
      continue;
    else if(equal(t.substr(i, m), p))
    {
      answer.push_back(i + 1);
    }
  }
}

int main()
{
  std::ifstream fin;
  std::ofstream fout;
  fin.open("search2.in");
  fout.open("search2.out");
  std::string p, t;
  fin >> p >> t;
  std::vector<int> degree_x;
  std::vector<int> answer;
  int val = 1;
 	for (int i = 0; i < p.size() + 1; i++)
  {
    degree_x.push_back(val);
    val *= x;
  }

  std::vector<int> H(t.size() - p.size() + 1, 0);
  Rabin_Karp(t, p, H, degree_x, answer);
  fout << answer.size() << '\n';
  for (auto el : answer)
  {
    fout << el << " ";
  }
  fin.close();
  fout.close();
  return 0;
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
W
Wataru, 2021-05-10
@Nikitos2002

Perhaps there is an overflow. Make sure that all hashes everywhere are considered only with the participation of unsigned types. Overflow in signed is Undefined behavior.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question