A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Algoritmos de Pesquisa em Cadeias de Caracteres Referências: Robert Sedgewick, Algorithms in C++, Addison-Wesley 1992, Cap. 19. W. B. Frakes e R. Baeza-Yates,

Apresentações semelhantes


Apresentação em tema: "Algoritmos de Pesquisa em Cadeias de Caracteres Referências: Robert Sedgewick, Algorithms in C++, Addison-Wesley 1992, Cap. 19. W. B. Frakes e R. Baeza-Yates,"— Transcrição da apresentação:

1 Algoritmos de Pesquisa em Cadeias de Caracteres Referências: Robert Sedgewick, Algorithms in C++, Addison-Wesley 1992, Cap. 19. W. B. Frakes e R. Baeza-Yates, Information Retrieval- Data Structures and Algorithms, Prentice-Hall 1992, Cap. 10.

2 Problema Problema da Pesquisa em Strings –encontrar todas as ocorrências de um padrão de comprimento m num texto de comprimento n –texto e padrão são cadeias de caracteres sobre o mesmo alfabeto –com m fixo, esforço computacional é O(n) no pior caso –é preciso inspeccionar n-m+1 caracteres no pior caso –factor constante na eficiência depende muito do algoritmo

3 Algoritmo exaustivo Princípio: tentar identificar o padrão em cada subcadeia de comprimento m do texto Exemplo

4 Algoritmo exaustivo public static int pesquisa(String padrao, String texto) { int t, p; int tamPadrao = padrao.length(); int tamTexto = texto.length(); for( t=0, p=0; p < tamPadrao && t < tamTexto; t++, p++) if( texto.charAt(t) != padrao.charAt(p) ) {t = t - p; p = -1; } if (p==tamPadrao) return t - tamPadrao; else return -1; }

5 Algoritmo Knuth-Morris-Pratt Princípio: usar informação obtida em cada falsa partida –quando a comparação falha, parte dos caracteres estão já examinados e estão no padrão –pré-processando a string do padrão, determina-se onde recomeçar quando uma comparação falha –não é necessário retroceder no texto; retrocede-se só no padrão Como saber para onde retroceder no padrão: –calcular para cada posição do padrão next[j] = max{ i | (pad[k] = pad[j-i+k] para k= 1,... i-1) e pad[k] pad[j]}

6 Algoritmo KMP Processamento do padrão resulta em next[j] –é o valor de k

7 Exemplo Algoritmo KMP Exemplo de padrão a b r a c a d a b r a –Para onde retroceder em caso de falha da comparação a b r a c a d a b r a next[j] –comparações quem a abra abracadabra abracadabra f alha em j=0, avançar e recomeçar em 0 abracadabra falha em j= 1, recomeçar em 0....

8 Exemplo Algoritmo KMP Exemplo de padrão a b r a c a d a b r a –Para onde retroceder em caso de falha da comparação a b r a c a d a b r a next[j] –comparações a b r a c a d a b r a m... avançar e recomeçar em 0 a m... recomeçar em 0 a b m... recomeçar em 0 a b r m... avançar e recomeçar em 0 a b r a m... recomeçar em 1

9 Exemplo Algoritmo KMP

10 jnext[j] melhor next[j] next[j] no KMP

11 Implementação KMP public static int kmp(String padrao, String texto) { int t, p; int tamPadrao = padrao.length(); int tamTexto = texto.length(); int next[] = new int[tamPadrao]; iniciar(tamPadrao, padrao, next); for( t=0, p=0; p < tamPadrao && t < tamTexto; t++, p++) while( (p >= 0) && (texto.charAt(t) != padrao.charAt(p))) p = next[p]; if (p==tamPadrao) return t - tamPadrao; else return -1; }

12 Posições de retrocesso public static void iniciar(int tam, String padrao, int next[]) { int i, j; next[0] = -1; for( i = 0, j = -1; i < tam-1; i++; j++; next[i] = j) while( (j>= 0) && (padrao.charAt(i) != padrao.charAt(j)) ) j = next[j]; }

13 Posições de retrocesso public static void iniciar(int tam, String padrao, int next[]) { int i, j; next[0] = -1; for( i = 0, j = -1; i < tam-1; ) { while( (j>= 0) && (padrao.charAt(i) != padrao.charAt(j)) ) j = next[j]; i++; j++; if(padrao.charAt(i) == padrao.charAt(j)) next[i] = next[j]; else next[i] = j)) } }

14 Cálculo de posições de retrocesso i=0j=-1next[0] = -1 j >= 0 i=1j=0next[1] = 0 j >= 0 p[1] != p[0]j = next[0] = -1 j >= 0 i=2j=0next[2] = 0 j >= 0 p[2] != p[0] i=3j=1next[3] = 1 j >= 0 p[3] != p[1] i=4j=2next[4] = 2 j >= 0 p[4] != p[2] j = next[2] = 0 j >= 0 p[4] != p[0] j = next[0] = -1 j >= 0

15 Cálculo de posições de retrocesso i=5j=0next[5] = 0 j >= 0 p[5] != p[0] i=6j=1next[6] = 1 j >= 0 p[6] != p[1] j = next[1] = 0 j >= 0 p[6] != p[0] i=7j=1next[7] = 1 j >= 0 p[7] != p[1]

16 Exemplo abracadabra i=0j=-1next[0] = -1 j >= 0 i=1j=0next[1] = 0 j >= 0 p[1] != p[0]j = next[0] = -1 j >= 0 i=2j=0next[2] = 0 j >= 0 p[2] != p[0] j = next[0] = -1 j >= 0 i=3j=0next[3] = 0 j >= 0 p[3] != p[0] i=4j=1next[4] = 1 j >= 0 p[4] != p[1] j = next[1] = 0 j >= 0 p[4] != p[0] j = next[0] = -1 j >= 0

17 Exemplo abracadabra i=5j=0next[5] = 0 j >= 0 p[5] != p[0] i=6j=1next[6] = 1 j >= 0 p[6] != p[1] j = next[1] = 0 j >= 0 p[6] != p[0] j = next[0] = -1 j >= 0 i=7j=0next[7] = 0 j >= 0 p[7] != p[0] i=8j=1next[8] = 1 j >= 0 p[8] != p[1] i=9j=2next[9] = 2 j >= 0 p[9] != p[2] i=10j=3next[10]= 3

18 Algoritmo Boyer-Moore Princípio: fazer comparações da direita para a esquerda do padrão –quando a comparação falha no fim do padrão, pode não ser necessário analisar o início –pré-processando a string do padrão, determina-se o tamanho do salto possível no texto quando uma comparação falha –requer buffer para o texto se este provém de dispositivo auxiliar Heurísticas para avançar no texto: –heurística de concordância: quando o padrão desliza tem de continuar a concordar nos caracteres que concordavam trazer um carácter diferente para a posição de discordância no texto –heurística do carácter discordante: o padrão desliza até alinhar a posição de discordância no texto com a primeira posição no padrão que concorda com ela

19 Algoritmo Boyer-Moore Processamento do padrão resulta em skip[j] –é o número de caracteres que o padrão pode ser chegado para a direita, quando falha uma comparação detectou-se discordância na posição j do padrão (contagem da direita) há j caracteres já vistos do texto que coincidem com os últimos j do padrão pode avançar-se skip[j] posições no texto e recomeçar a comparação com o fim do padrão –saltos são para avançar ponteiro do texto –quando se salta, o ponteiro do padrão é reposto no fim deste Algoritmo original combina as 2 heurísticas, usando o maior dos saltos calculados

20 Algoritmo Boyer-Moore Heurística de concordância –deslizar uma cópia do padrão sobre si próprio, da esquerda para a direita; cópia serve como padrão a alinhar na parte conhecida do texto –começar com o penúltimo carácter do padrão sobre o último carácter do texto –parar quando todos os caracteres sobrepostos nos j finais coincidem, e o carácter na posição j não coincide Heurística do carácter discordante –decidir o que fazer com base no carácter do texto que causou a discordância –Pré-processamento: decidir, para cada carácter que pode ocorrer no texto, o que fazer se ele causar discordância –Tabela não é para posições no padrão mas para caracteres no alfabeto do texto –tamanho do salto só depende do carácter analisado, não depende de onde ele fez falhar a comparação; avança-se o ponteiro do texto até alinhar o carácter do texto com o primeiro ponto onde ele aparece no padrão (ocorrência mais à direita)

21 skip[j] com heurística de concordância jskip[j]

22 Boyer-Moore com heurística de concordância Exemplo de padrão a b r a c a d a b r a –Tamanho do salto em caso de falha da comparação j a b r a c a d a b r a skip[j] –comparações (indexação a partir da direita) quem a abra abracadabra abracadabra f alha em j=4, avançar 7 abracadabra falha em j= 1, avançar 3 abracadabra falha em j= 0, avançar 1

23 Boyer-Moore com heurística de carácter discordante Exemplo de padrão a b r a c a d a b r a –Tamanho do salto em caso de falha da comparação a b r c d alfabeto skip[letra] –comparações quem a abra abracadabra abracadabra f alha em símbolo a, avançar 1 abracadabra falha em símbolo não presente, abracadabra avançar 11

24 Implementação BM - carácter discordante public static int bm(String padrao, String texto) { int t, p, s; int tamPadrao = padrao.length(); int tamAlfa = 256; int tamTexto = texto.length(); int skip[] = new int[tamAlfa]; iniciarBm(tamAlfa, padrao, skip); for( t=tamPadrao-1, p=tamPadrao-1; p > 0; t--, p--) while( texto.charAt(t) != padrao.charAt(p) ) { s = skip[ index(texto.charAt(t))]; t += (tamPadrao - p > s) ? tamPadrao - p : s; if ( t >= tamTexto ) return tamTexto; p = tamPadrao-1; } return t; }

25 Algoritmo Rabin-Karp Princípio: tratar cada substring de tamanho M do texto como chave de uma tabela de dispersão –padrão é encontrado quando a chave da substring coincide com a do padrão –como se procura chave específica, não é preciso guardar a tabela, mas apenas calcular as chaves –com tabela virtual: grande tamanho reduz probabilidade de falsas escolhas Para ser método eficaz –cálculo da chave menos pesado que fazer as comparações –função de dispersão: h(k) = k mod qq primo elevado –cálculo das chaves: chave da posição i usa a da posição i-1 M caracteres transformam-se em número: empacotados na máquina como palavra, e esta interpretada como número

26 Algoritmo Rabin-Karp M caracteres a[i]... a[i+M-1] vistos como número inteiro –o mesmo que escrever os caracteres como inteiros em base d d: número de caracteres –número que representa os M caracteres x = a[i] d M-1 + a[i+1] d M a[i+M-1] –conhecendo h(x) = x mod q, é simples passar à chave da string 1 posição à frente (x - a[i] d M-1 )d + a[i+M] –propriedades da ar itmética modular para obter o resto da divisão por q da expressão que resulta de uma operação aritmética, pode operar-se com os valores intermédios em módulo q –implementação do algoritmo: calcular chave para o padrão e primeiros M caracteres calcular chaves para as posições sucessivas e comparar com a do padrão

27 Implementação RK public static int rk(String padrao, String texto) { int q = ; int d = 32; int tamPadrao = padrao.length(); int tamTexto = texto.length(); int i, dM = 1, h1 = 0, h2 = 0; for( i=1; i < tamPadrao; i++) dM = (d * dM) % q; for( i=0; i < tamPadrao; i++) { h1 = (h1 * d + index(padrao.charAt(i))) % q; h2 = (h2 * d + index(texto.charAt(i))) % q; } for( i = 0 ; h1 != h2; i++) { h2 = (h2 + d * q - index(texto.charAt(i)) * dM) % q; h2 = (h2 * d + index(texto.charAt(i+ tamPadrao))) % q; if( i > tamTexto - tamPadrao ) return tamTexto; } return i; }

28 Eficiência de pesquisa em texto Algoritmo exaustivo –pode requerer O(N M) comparações Algoritmo Knuth-Morris-Pratt –requer no pior caso N + M comparações –usa o texto sequencialmente, sem necessidade de recuar Algoritmo de Boyer-Moore – requer no pior caso N + M comparações –caso médio muito mais favorável: estimado em N/M para alfabeto significativamente maior que padrão Algoritmo de Rabin-Karp –estimado em O(N), se não ocorrem colisões de chaves


Carregar ppt "Algoritmos de Pesquisa em Cadeias de Caracteres Referências: Robert Sedgewick, Algorithms in C++, Addison-Wesley 1992, Cap. 19. W. B. Frakes e R. Baeza-Yates,"

Apresentações semelhantes


Anúncios Google