Algoritmo KMP para Correspondência de Padrões em Strings

Princípio do Algoritmo KMP

O algoritmo KMP (Knuth-Morris-Pratt) é uma técnica eficiente para encontrar todas as ocorrências de um padrão dentro de um texto. Diferente da abordagem ingênua (força bruta), que tem complexidade O(mn) e realiza comparações redundantes, o KMP utiliza informações sobre o padrão para pular comparações desnecessárias, alcançando complexidade O(n + m).

Por exemplo, ao comparar o texto "ABCDABCDABDE" com o padrão "ABCDABD", após seis correspondências bem-sucedidas, a sétima falha. A força bruta reiniciaria a comparação a partir do segundo caractere do texto, mas o KMP aproveita a estrutura do padrão para otimizar o deslocamento.

Conceito de Border (Borda)

O KMP introduz o conceito de "border", que é o maior prefixo próprio que também é sufixo de uma string. Para a string "abcgab", o border tem compriemnto 2 (correspondendo a "ab"). Esse conceito permite que, em caso de falha na comparação, o padrão seja deslocado de forma que o border já correspondido seja alinhado com o sufixo atual do texto, evitando reinícios do zero.

Construção do Array de Próximos (Next Array)

O array de próximos armazena o comprimento do border mais longo para cada prefixo do padrão. Sua construção é realizada por um processo semelhante a uma auto-correspondência do padrão, onde o padrão é comparado consigo mesmo.

// Construção do array next
int buildNextArray(string pattern) {
    int m = pattern.length();
    int nextArray[m];
    nextArray[0] = 0;
    int j = 0;
    for (int i = 1; i < m; i++) {
        while (j > 0 && pattern[i] != pattern[j]) {
            j = nextArray[j - 1];
        }
        if (pattern[i] == pattern[j]) {
            j++;
        }
        nextArray[i] = j;
    }
}

Algoritmo de Correspondência KMP

Com o array de próximos construído, a busca do padrão no texto é realizada percorrendo ambos simultaneamente. Quando ocorre uma falha, o padrão é deslocado usando o array de próximos, permitindo que a comparação continue de um ponto avançado.

// Algoritmo KMP para busca
void kmpSearch(string text, string pattern) {
    int n = text.length();
    int m = pattern.length();
    int nextArray[m];
    buildNextArray(pattern, nextArray);
    
    int j = 0;
    for (int i = 0; i < n; i++) {
        while (j > 0 && text[i] != pattern[j]) {
            j = nextArray[j - 1];
        }
        if (text[i] == pattern[j]) {
            j++;
            if (j == m) {
                cout << "Padrão encontrado na posição: " << i - j + 1 << endl;
                j = nextArray[j - 1]; // Permite sobreposições
            }
        }
    }
}

Floresta de Falha (Fail Tree)

O array de próximos pode ser interpretado como uma estrutura de árvore, onde cada nó i tem como pai o valor next[i-1]. Essa floresta de falha é útil em problemas avançados de strings, como manipulação de múltiplos padrões ou operações sobre sobreposições. Exemplos clásicos incluem problemas de template e zoo em competições de programação.

Tags: KMP string matching pattern recognition Next array border concept

Publicado em 6-28 09:08