Algoritmo de Knuth-Morris-Pratt - KMP

6,128 views 36 slides Nov 18, 2015
Slide 1
Slide 1 of 36
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36

About This Presentation

Algoritmo de Knuth-Morris-Pratt - KMP


Slide Content

Algoritmo KMP ( Knuth -Morris- Pratt ) Curso de Maratona de Programação ICT-Unifesp - SJC

KMP Para que serve? Saber se uma string é substring de outra. String searching algorithm . É legal? Sim, você escreve pouco (código pequeno) e é eficiente ! Vídeo-aula utilizando esses slides: https :// youtu.be/VxcrVqoi_k8 2

KMP Ideia do algoritmo: Procura uma palavra (padrão) P dentro de um texto T. Quando aparece uma diferença ( mismatch ), a palavra tem em si a informação necessária para determinar onde começar a próxima comparação, ou seja, um mistmach consiste em caracteres que já conhecemos porque eles estão na palavra/padrão (isso evita retroceder pelos caracteres já conhecidos). Pense: considerando um algoritmo de força bruta, quando ocorre uma diferença entre T[i] e P[j], não seria possível fazer um deslocamento maior de P para a direita evitando comparações redundantes? 3

KMP Ideia do algoritmo: A B A A B X A B A A B A i j T P o maior prefixo que é sufixo é o AB 4

KMP T[i] != P[j] A B A A B X A B A A B A i j T P pode-se recomeçar a partir daqui essas comparações não precisam ser refeitas 5

KMP Exemplo: texto = "eu gosto de c++" palavra: "gosto" A palavra "gosto" foi encontrada na posição 3 (indexando a partir do 0). 6

KMP Aplicação: Quando você utiliza um editor de sua preferência e quer buscar uma string em um arquivo, esses tipos de algoritmos são utilizados para exibir os resultados da busca. 7

KMP Complexidade: A complexidade no pior caso é O(n) onde “n” é o tamanho do texto em que a palavra será buscada. Um algoritmo ruim teria complexidade O(n * m) onde “n” seria o tamanho do texto e “m” o tamanho da palavra. Duas etapas: prefix function s tring matching 8

KMP Prefix function : KMP faz um pré-processamento da palavra (padrão) e constrói um array auxiliar (vou chamá-lo de “ aux ”) de tamanho “m” (mesmo tamanho da palavra). O pré-processamento analisa todos os prefixos do padrão procurando pelo maior sufixo destes prefixos que também seja prefixo. O pré-processamento evita que um caractere seja reexaminado! Exemplo: ABAB O maior sufixo que também é prefixo é o “AB” que termina na posição 1 (indexando a partir do 0) e também ocorre na posição 2. 9

KMP Prefix function : Ao final, teremos um array que conterá cada posição que gera um prefixo para cada posição do padrão. O pré-processamento é feito na palavra (padrão) para determinar se seus prefixos aparecem como subsequências deles mesmos. O array que iremos construir nessa fase chamaremos de “ aux ” de forma que: O tamanho do maior prefixo de aux [0..k] que é sufixo de aux [1..k]. Ou seja, é o tamanho do maior “começo” de aux [k] que também aparece no seu “fim” sem condiderar ele mesmo. 10

KMP Prefix function 11

KMP Considere a palavra: ABCDABCA A B C D A B C A j i 1 2 3 4 5 6 7 A == B ? Não, coloca 0 na posição marcada por “i” e incrementa “i” 12

KMP Considere a palavra: ABCDABCA A B C D A B C A j i 1 2 3 4 5 6 7 A == C ? Nãão , coloca 0 na posição marcada por “i” e incrementa “i” 13

KMP Considere a palavra: ABCDABCA A B C D A B C A j i 1 2 3 4 5 6 7 A == D ? Nããão , coloca 0 na posição marcada por “i” e incrementa “i” 14

KMP Considere a palavra: ABCDABCA A B C D A B C A j i 1 2 3 4 5 6 7 A == A ? Sim, incrementa “j”, guarda o valor de “j” na posição marcada por “i” e incrementa o “i” 15

KMP Considere a palavra: ABCDABCA A B C D A B C A j i 1 2 3 4 5 6 7 1 B == B ? Simm , incrementa “j”, guarda o valor de “j” na posição marcada por “i” e incrementa o “i” 16

KMP Considere a palavra: ABCDABCA A B C D A B C A j i 1 2 3 4 5 6 7 1 2 C == C ? Simmm , incrementa “j”, guarda o valor de “j” na posição marcada por “i” e incrementa o “i” 17

KMP Considere a palavra: ABCDABCA A B C D A B C A j i 1 2 3 4 5 6 7 1 2 3 D == A ? Não, mas o j é diferente de 0, então podemos fazer: j = aux [j – 1], o u seja, j = 0, não incrementa o “i” e nem o “j’ 18

KMP Considere a palavra: ABCDABCA A B C D A B C A j i 1 2 3 4 5 6 7 1 2 3 Voltamos tudo de novo :(, calma, está terminando... A == A ? Sim, incrementa “j”, guarda o valor de “j” na posição marcada por “i” e incrementa o “i” 19

KMP Considere a palavra: ABCDABCA A B C D A B C A j 1 2 3 4 5 6 7 1 2 3 1 i = 8, ou seja, não é menor do que o tamanho da palavra ABCDABCA, portanto, chegamos ao fim da execução. 20

KMP Algoritmo da fase de pré-processamento ( prefix function ): substr = palavra = padrão 21

KMP String matching 22

KMP Vamos tentar identificar a palavra “CD” Primeiro fazemos o pré-processamento construindo o vetor “ aux ” para o padrão que se quer encontrar. idx_substr -> índice da substring /palavra/padrão idx_str -> índice da string /texto idx_substr = idx_str = 0 C D 1 23

KMP Vamos tentar identificar a palavra “CD” C D 1 Critério de parada: idx_str < tam_str 24

KMP Vamos tentar identificar a palavra “ C D” A B C D A B C A Lembrando que idx_substr = 0 e idx_str = 0 substr [ idx_substr ] == str [ idx_str ] ? C == A ? Não ( mismatch ) 25

KMP Vamos tentar identificar a palavra “ C D” A B C D A B C A Lembrando que idx_substr = 0 e idx_str = 0 idx_substr == tam_substr ? 0 == 2 ? Não, ou seja, a palavra ainda não foi encontrada no texto. 26

KMP Vamos tentar identificar a palavra “ C D” A B C D A B C A Lembrando que idx_substr = 0 e idx_str = 0 // mismatches após idx_substr matches idx_str < tam_str E substr [ idx_substr ] != str [ idx_str ] ? Ou seja, 0 < 8 E C != A ? Sim, então verificamos: idx_substr != 0 ? Não, então idx_str = idx_str + 1 = 1 27

KMP Vamos tentar identificar a palavra “ C D” A B C D A B C A idx_substr = 0 e idx_str = 1 substr [ idx_substr ] == str [ idx_str ] ? C == B ? Não. idx_substr == tam_substr ? 0 == 2 ? Não. idx_str < tam_str E substr [ idx_substr ] != str [ idx_str ] ? 1 < 8 E C != B ? Sim. idx_substr != 0 ? Não, então idx_str = idx_str + 1 = 2 28

KMP Vamos tentar identificar a palavra “ C D” A B C D A B C A idx_substr = 0 e idx_str = 2 substr [ idx_substr ] == str [ idx_str ], C == C ? Sim, então incrementa idx_substr e idx_str em 1 Agora idx_substr = 1 e idx_str = 3 idx_substr == tam_substr ? 1 == 2 ? Não, ainda não encontramos o padrão. idx_str < tam_str E substr [ idx_substr ] != str [ idx_str ] ? Não, porque D == D! 29

KMP Vamos tentar identificar a palavra “C D ” A B C D A B C A idx_substr = 1 e idx_str = 3 substr [ idx_substr ] == str [ idx_str ], D == D ? Sim, então incrementa idx_substr e idx_str em 1 Agora idx_substr = 2 e idx_str = 4 idx_substr == tam_substr ? 2 == 2 ? Sim, então imprime que o padrão foi encontrado. 30

KMP Vamos tentar identificar a palavra “C D ” A B C D A B C A idx_substr = 2 e idx_str = 4 Após a impressão do padrão encontrado, é feito: idx_substr = aux [ idx_substr – 1] Aqui utilizamos o array que construímos no pré-processamento. idx_substr = aux [2 – 1] = aux [1] -> idx_substr = 0 Aqui não fez muita diferença, pois nosso padrão é apenas “CD”, o importante é que nessa parte tenta evitar comparações descenessárias fazendo uso do array “ aux ”. C D 1 31

KMP Vamos tentar identificar a palavra “CD” A B C D A B C A E assim sucessivamente, o algoritmo encontra todas as posições do padrão buscado no texto e de forma rápida: O(n)! 32

KMP Algoritmo da etapa string matching : 33

KMP Algoritmo: https:// goo.gl/ybXQqN ou https :// gist.github.com/marcoscastro/618bcfc9ec58e3b27661 Implementação em C++: https:// goo.gl/g0mrcL ou https:// gist.github.com/marcoscastro/55cc08aef269d6d006d2 Vídeo-aula: https:// youtu.be/VxcrVqoi_k8 34

Considerações sobre strings Se eu tenho só duas strings e quero achar uma dentro da outra, o que eu posso usar para otimizar? Resposta: KMP. Se eu tenho várias strings e quero encontrar a ocorrência delas em uma única string , o que eu posso usar para otimizar? Resposta: Suffix Tree ou Suffix Array . Otimização: algoritmo de Ukkonen para construir a suffix tree . E a Trie (árvore de prefixo)? Uma alternativa ao map. 35

Contato [email protected] www.geeksbr.com www.twitter.com/mcastrosouza 36