E101. Algoritmo Рабина-Карпа поиска подстроки в строке за O (N)

e-maxx algorithm original: C/C++ #algorithm #emaxx #hashing #search #string
O texto da tarefa é traduzido do russo para o idioma selecionado. O código permanece sem alterações.

Источник: e-maxx.ru/algo, страница PDF 301.

Этот Algoritmo базируется на хэшировании строк, и тех, кто не знаком с темой, отсылаю к "Algoritmoам хэширования в Tarefaх на строки".

Авторы Algoritmoа - Рабин (Rabin) и Карп (Karp), 1987 год. Дана string S и текст T, состоящие из маленьких латинских букв. it is required find все вхождения строки S в текст T за время O (|S| + |T|). Algoritmo. Посчитаем хэш для строки S. Посчитаем значения хэшей для всех префиксов строки T. Теперь переберём все подстроки T длины |S| и каждую сравним с |S| за время O (1).

Implementação

string s, t; // Entradaные данные

// считаем все степени p

const int p = 31;

vector<long long> p_pow (max (s.length(), t.length()));

p_pow[0] = 1;

for (size_t i=1; i<p_pow.size(); ++i)

p_pow[i] = p_pow[i-1] * p;

// считаем хэши от всех префиксов строки T

vector<long long> h (t.length());

for (size_t i=0; i<t.length(); ++i)

{

h[i] = (t[i] - 'a' + 1) * p_pow[i];

if (i)  h[i] += h[i-1];

}

// считаем хэш от строки S

long long h_s = 0;

for (size_t i=0; i<s.length(); ++i)

h_s += (s[i] - 'a' + 1) * p_pow[i];

// перебираем все подстроки T длины |S| и сравниваем их

for (size_t i = 0; i + s.length() - 1 < t.length(); ++i)

{

long long cur_h = h[i+s.length()-1];

if (i)  cur_h -= h[i-1];

// приводим хэши к одной степени и сравниваем

if (cur_h == h_s * p_pow[i])

cout << i << ' ';

}

C# solução

rascunho automático, revisar antes de enviar
using System;
using System.Collections.Generic;
using System.Linq;

public static class AlgorithmDraft
{
    // Auto-generated C# draft from the original e-maxx C/C++ listing. Review before production use.
    string s, t; // входные данные
    // считаем все степени p
    const int p = 31;
    vector<long> p_pow (max (s.length(), t.length()));
    p_pow[0] = 1;
    for (size_t i=1; i<p_pow.size(); ++i)
            p_pow[i] = p_pow[i-1] * p;
    // считаем хэши от всех префиксов строки T
    vector<long> h (t.length());
    for (size_t i=0; i<t.length(); ++i)
    {
            h[i] = (t[i] - 'a' + 1) * p_pow[i];
            if (i)  h[i] += h[i-1];
    }
    // считаем хэш от строки S
    long h_s = 0;
    for (size_t i=0; i<s.length(); ++i)
            h_s += (s[i] - 'a' + 1) * p_pow[i];
    // перебираем все подстроки T длины |S| и сравниваем их
    for (size_t i = 0; i + s.length() - 1 < t.length(); ++i)
    {
            long cur_h = h[i+s.length()-1];
            if (i)  cur_h -= h[i-1];
            // приводим хэши к одной степени и сравниваем
            if (cur_h == h_s * p_pow[i])
                    Console.WriteLine( i << ' ';
    }
}

C++ solução

correspondente/original
string s, t; // входные данные
// считаем все степени p
const int p = 31;
vector<long long> p_pow (max (s.length(), t.length()));
p_pow[0] = 1;
for (size_t i=1; i<p_pow.size(); ++i)
        p_pow[i] = p_pow[i-1] * p;
// считаем хэши от всех префиксов строки T
vector<long long> h (t.length());
for (size_t i=0; i<t.length(); ++i)
{
        h[i] = (t[i] - 'a' + 1) * p_pow[i];
        if (i)  h[i] += h[i-1];
}
// считаем хэш от строки S
long long h_s = 0;
for (size_t i=0; i<s.length(); ++i)
        h_s += (s[i] - 'a' + 1) * p_pow[i];
// перебираем все подстроки T длины |S| и сравниваем их
for (size_t i = 0; i + s.length() - 1 < t.length(); ++i)
{
        long long cur_h = h[i+s.length()-1];
        if (i)  cur_h -= h[i-1];
        // приводим хэши к одной степени и сравниваем
        if (cur_h == h_s * p_pow[i])
                cout << i << ' ';
}

Java solução

rascunho automático, revisar antes de enviar
import java.util.*;
import java.math.*;

public class AlgorithmDraft {
    // Auto-generated Java draft from the original e-maxx C/C++ listing. Review before production use.
    string s, t; // входные данные
    // считаем все степени p
    const int p = 31;
    vector<long> p_pow (max (s.length(), t.length()));
    p_pow[0] = 1;
    for (size_t i=1; i<p_pow.size(); ++i)
            p_pow[i] = p_pow[i-1] * p;
    // считаем хэши от всех префиксов строки T
    vector<long> h (t.length());
    for (size_t i=0; i<t.length(); ++i)
    {
            h[i] = (t[i] - 'a' + 1) * p_pow[i];
            if (i)  h[i] += h[i-1];
    }
    // считаем хэш от строки S
    long h_s = 0;
    for (size_t i=0; i<s.length(); ++i)
            h_s += (s[i] - 'a' + 1) * p_pow[i];
    // перебираем все подстроки T длины |S| и сравниваем их
    for (size_t i = 0; i + s.length() - 1 < t.length(); ++i)
    {
            long cur_h = h[i+s.length()-1];
            if (i)  cur_h -= h[i-1];
            // приводим хэши к одной степени и сравниваем
            if (cur_h == h_s * p_pow[i])
                    System.out.println( i << ' ';
    }
}

Материал разбит как Algoritmoическая Tarefa: изучить постановку, понять асимптотику и реализовать Algoritmo на выбранном языке.

Vacancies for this task

vagas ativas with overlapping task tags are mostradas.

Todas as vagas
Ainda não há vagas ativas.