Подтвердить что ты не робот

Префиксная таблица KMP

Я читаю о KMP для соответствия строк.
Ему нужна предварительная обработка шаблона, создавая таблицу префиксов.
Например, для строки ababaca таблица префикса: P = [0, 0, 1, 2, 3, 0, 1]
Но я не понимаю, что показывают цифры. Я читал, что он помогает находить совпадения шаблона, когда он сдвигается, но я не могу подключить эту информацию к номерам в таблице.

4b9b3361

Ответ 1

Каждое число принадлежит соответствующему префиксу ("a", "ab", "aba",...) и для каждого префикса представляет длину самого длинного суффикса этой строки, который соответствует префиксу. Здесь мы не считаем всю строку суффиксом или префиксом, она называется само-суффиксом и само-префиксом (по крайней мере, на русском языке, не уверен насчет английских терминов).

Итак, у нас есть строка "ababaca". Давай посмотрим на это. KMP вычисляет функцию префикса для каждого непустого префикса. Давайте определим s[i] как строку, p[i] как функцию префикса. префикс и суффикс могут перекрываться.

+---+----------+-------+------------------------+
| i |  s[0:i]  | p[i]  | Matching Prefix/Suffix |
+---+----------+-------+------------------------+
| 0 | a        |     0 |                        |
| 1 | ab       |     0 |                        |
| 2 | aba      |     1 | a                      |
| 3 | abab     |     2 | ab                     |
| 4 | ababa    |     3 | aba                    |
| 5 | ababac   |     0 |                        |
| 6 | ababaca  |     1 | a                      |
|   |          |       |                        |
+---+----------+-------+------------------------+

Простой C++ код, который вычисляет префиксную функцию строки S:

vector<int> prefixFunction(string s) {
    vector<int> p(s.size());
    int j = 0;
    for (int i = 1; i < (int)s.size(); i++) {
        while (j > 0 && s[j] != s[i])
            j = p[j-1];

        if (s[j] == s[i])
            j++;
        p[i] = j;
    }   
    return p;
}

Ответ 2

Этот код может быть не самым коротким, но простым для понимания потоком кода. Простой Java-код для вычисления префикса Array-

    String pattern = "ababaca";
    int i = 1, j = 0;
    int[] prefixArray = new int[pattern.length];
    while (i < pattern.length) {

        while (pattern.charAt(i) != pattern.charAt(j) && j > 0) {
            j = prefixArray[j - 1];

        }
        if (pattern.charAt(i) == pattern.charAt(j)) {
            prefixArray[i] = j + 1;
            i++;
            j++;

        } else {
            prefixArray[i] = j;
            i++;
        }
    }

    for (int k = 0; k < prefixArray.length; ++k) {
        System.out.println(prefixArray[k]);
    }

Он производит требуемый output-

0 0 1 2 3 0 1

Ответ 3

строка text = "ababbabbababbababbabb";   static int arr [30];

int i = 1;
while (i < text.length())
{
    int j = 0;
    int value = 0;
    while (((i + j) < text.length()) && (text[j] == text[i + j]))
        val[i + j] = ++value, j++;
    i += j + 1;
}

требуемый вывод хранится в val []

Ответ 4

Реализация на Python

p='ababaca'

l1 = len(p)

j = 0
i = 1
prefix = [0]

while len(prefix) < l1:
    if p[j] == p[i]:
        prefix.append(j+1)
        i += 1
        j += 1
    else:
        if j == 0:
            prefix.append(0)
            i += 1
        if j != 0:
            j = prefix[j-1]

print prefix