\subsection*{Casamento de Padr\~ao com Busca Aproximada} O objetivo deste trabalho \'{e} projetar e implementar um sistema de programas para recuperar ocorr\^encias de padr\~oes em arquivos constitu\'{\i}dos de documentos, utilizando algoritmos lineares de busca sequencial. %\vspace{-0.2cm} \subsubsection*{Busca} \label{Busca} %\vspace{-0.2cm} O sistema de programas recebe do usu\'ario uma cadeia de caracteres, se a busca \'e exata ($k=0$) ou aproximada ($0 < k < m$), e imprime todas as ocorr\^encias do padr\~ao no texto. Nesta parte do trabalho voc\^e dever\'a utilizar os seguintes algoritmos: \begin{itemize} \item Algoritmo de Boyer-Moore-Horspool (BMH) para casamento exato de padr\~oes \item Algoritmo Shift-And para casamento exato de padr\~oes \item Algoritmo Shift-And para casamento aproximado de padr\~oes % e que pode ser obtido em %{\tt http://www.dcc.ufmg.br/$\sim$nivio/pa00/tp3}. \end{itemize} \subsubsection*{2 Pontos extras} \begin{itemize} \item Apresente a implementa\c{c}\~ao em Pascal dos algoritmos Shift-And para (i) casamento exato e (ii) casamento aproximado. Procure realizar as opera\~oes {\em or}, {\em and} e deslocamento ($>>$) da maneira mais eficiente poss\'{\i}vel, mas sem perder a eleg\^ancia e a clareza. \item Compare o desempenho das implementa\c{c}\~oes em Pascal e C. \end{itemize} \subsubsection*{Como fazer} Utilize os arquivos de documentos da cole\c{c}\~ao TREC dispon\'{\i}vel em {\tt /export/texto2/wsj}, com as seguintes caracter\'{\i}sticas:\\ \begin{tabular}{|l|c|} \hline Cole\c{c}\~ao & Tamanho (Mb) \\ wsj88 & 109 \\ wsj88\_10 & 10 \\ wsj88\_20 & 20 \\ wsj89 & 2.8 \\ \hline \end{tabular} \vspace{0.4cm} \noindent Um exemplo de registro deste arquivo \'e: %\vspace{-0.5cm} {\small \begin{verbatim} WSJ890802-0125
= 890802
890802-0125. Inside Track: @ NCNB Director Sold Big Holding in July @ Worth $7.4 Million More 4 Weeks Later @ ---- @ By Alexandra Peers and John R. Dorfman @ Staff Reporters of The Wall Street Journal
08/02/89
WALL STREET JOURNAL (J) NCB BPCO TRN EGGS LABOR STOCK MARKET, OFFERINGS (STK) SECURITIES INDUSTRY (SCR) Even insiders make mistakes. Sometimes, big, fat, $7 million-dollar mistakes. ...
\end{verbatim} } \noindent {\bf Observa\c{c}\~oes:} \begin {enumerate} \item Crie uma interface de uso do seu sistema parecida com a do sistema {\em agrep} dispon\'{\i}vel na rede do DCC. \item A sa\'{\i}da do programa deve mostrar a linha do documento que cont\^em o padr\~ao. \item Para testar seu programa voc\^e deve realizar as consultas listadas no arquivo {\tt /export/texto2/wsj\_consultas} e mostrar o resultado obtido. \item O sistema {\em agrep} dispon\'{\i}vel na rede do DCC pode ser um bom par\^ametro para comparar o desempenho da sua implementa\c{c}\~ao em rela\c{c}\~ao a uma implementa\c{c}\~ao considerada r\'apida. \item A principal refer\^encia \'e o Cap\'{\i}tulo 7 indicado acima. As refer\^encias ao final do texto s\~ao apenas complementares, e o TP3 poder\'a ser feito independente delas. \end {enumerate} \noindent {\bf O que deve ser entregue:} \begin {itemize} \item Explica\c{c}\~ao suscinta dos algoritmos e estruturas de dados utilizados para resolver o problema. (2 pontos) %\item An\'alise de complexidade dos principais algoritmos implementados. %(1 ponto) \item Listagem dos programas implementados. O c\'odigo deve ser bem comentado e organizado. (4 pontos) \item Resultados de experimentos para avaliar empiricamente o desempenho dos algoritmos, usando tempo de rel\'ogio. (4 pontos) \end{itemize} \noindent {\bf Refer\^encias:} %\medskip \noindent Wu, S. and Manber, U. (1992) Fast Text Searching Allowing Errors, Communications of the ACM, pp. 83-91, v. 35(10). %\medskip \noindent Andrew Hume, Daniel Sunday: Fast String Searching. Software - Practice and Experience 21(11): 1221-1248 (1991). \noindent Baeza-Yates, R. e R\'egnier, M. (1992) ``Average Running Time of the Boyer-Moore-Horspool Algorithm'', {\em Theoretical Computer Science 92}(1), 19--31. %\medskip \noindent Daniel Sunday: A Very Fast Substring Search Algorithm. CACM 33(8): 132-142 (1990). %\vspace{0.3cm} %\noindent %{\bf C\'odigo:} % %A seguir \'e apresentado um c\'odigo exemplo. Ele faz busca sequencial %em textos. % %{\small %\begin{verbatim} % %============================================================================== %/* %Autor : Marcio Drumond Araujo - 1997 %Descricao: Implementacao do algoritmo de Wu e Manber desenvolvido em 1992 % considerando a busca somente de palavras inteiras %*/ % %/* /// I N C L U D E S ///////////////////////////////////////////////////// */ % %#include % %/* /// D E F I N E S /////////////////////////////////////////////////////// */ % %#define TRUE 1 %#define FALSE 0 %#define ALPHABET_SIZE 256 %#define MAX_LINE_SIZE 512 %#define MAX_MODIFIED_LINE_SIZE 512 %#define MAX_PATTERN_SIZE 29 /* considerando uma palavra de 32 bits */ %#define MAX_NUMBER_OF_ERRORS 28 /* considerando uma palavra de 32 bits */ %#define MAX_FILE_NAME_SIZE 256 % %/* /// G L O B A L V A R I A B L E S ///////////////////////////////////// */ % %long S[ALPHABET_SIZE], /* mascaras dos caracteres do alfabeto */ % valid[ALPHABET_SIZE], /* diz se o caractere faz parte de palavras */ % Start[MAX_NUMBER_OF_ERRORS], /* mascaras de inicializacao */ % M; /* mascara que diz onde a busca % obrigatoriamente e' exata no padrao */ % %/* /// F U N C T I O N S /////////////////////////////////////////////////// */ % %/* Funcao : preproc % Objetivos : preprocessar o padrao, montando as mascaras de inicializacao, % dos caracteres do alfabeto e a de busca exata obrigatoria % Parametros: o padrao e o numero de erros % Saida : nenhuma */ %void preproc(char *p, long k) { % int i, % j, % m; /* pattern size */ % % m = strlen(p); % for (i = 0; i < (k + 1); i++) { /* inicializa mascaras de inicializacao */ % Start[i] = 0; % for (j = 0; j <= i; j++) { % Start[i] |= 1 << (m - j); % } % } % for (i = 0; i < ALPHABET_SIZE; i++) { % S[i] = 0; % valid[i] = ((i >= 'a') && (i <= 'z')) || ((i >= 'A') && (i <= 'Z')); % } % M = 0; % for (i = 0; i < m; i++) { /* inicializa mascaras de caracteres do alfabeto */ % if (((p[i] >= 'a') && (p[i] <= 'z')) || ((p[i] >= 'A') && (p[i] <= 'Z'))) { % S[p[i]] |= 1 << (m - 1 - i); % M |= 1 << (m - 1 - i); % } % else { % S[' '] |= 1 << (m - 1 - i); % } % } % for (i = 0; i < ALPHABET_SIZE; i++) { % if (!valid[i]) { % S[i] = S[' ']; % } % } %} % %/* Funcao : Wu_Manber % Objetivos : verifica se um padrao ocorre ou nao numa sequencia, com um % numero de erros menor ou igual a k % Parametros: o padrao, a sequencia e o numero de erros % Saida : verdadeiro se o padrao ocorre na sequencia ou falso, caso % contrario */ %long Wu_Manber(char *p, char *t, long k) { % long i, % j, % m, /* tamanho do padrao */ % n, /* tamanho da sequencia */ % matchfound, /* diz se um casamento foi encontrado */ % R0[MAX_NUMBER_OF_ERRORS], /* mascaras de estado anterior */ % R1[MAX_NUMBER_OF_ERRORS]; /* mascaras de estado atual */ % char newt[MAX_MODIFIED_LINE_SIZE]; /* sequencia entre espacos */ % % strcpy(newt, " "); % strcat(newt, t); % strcat(newt, " "); % n = strlen(newt); % m = strlen(p); % matchfound = FALSE; % for (i = 0; i <= k; i++) { /* inicializa mascaras de estado */ % R1[i] = Start[i]; % R0[i] = Start[i]; % } % for (i = 0; i < n; i++) { /* executa o algoritmo */ % R1[0] = ((R0[0] >> 1) & S[newt[i]]) | (Start[0] & R0[0]); % for (j = 1; j <= k; j++) { % R1[j] = ((R0[j] >> 1) & S[newt[i]]) | % ((R0[j-1] | ((R1[j-1] | R0[j-1]) >> 1)) & M) | (Start[0] & R0[j]); % } % for (j = 0; j <= k; j++) { /* atribui estado atual no anterior */ % R0[j] = R1[j]; % if (R1[j] & 1) { /* se bit menos significativo estiver ativo, entao % tem-se um casamento na linha atual do texto */ % matchfound = TRUE; % } % } % } % return matchfound; %} % %/* /// M A I N F U N C T I O N /////////////////////////////////////////// */ % %int main(int argc, char *argv[]) { % FILE *t; /* text file id */ % char line[MAX_LINE_SIZE], /* linha do arquivo texto */ % p[MAX_PATTERN_SIZE], /* padrao a ser pesquisado */ % filename[MAX_FILE_NAME_SIZE]; /* nome do arquivo texto */ % long i, % j, % m, /* tamanho do padrao */ % k; /* numero de erros */ % % if (argc != 4) { /* testa se o numero de argumentos esta correto */ % fprintf(stderr, "Numero incorreto de parametros\n"); % exit(1); % } % k = atoi(argv[1]); % if (k > MAX_NUMBER_OF_ERRORS) { /* valida o numero de erros da busca */ % fprintf(stderr, "Numero de erros maior que o maximo permitido\n"); % exit(1); % } % strcpy(p, " "); /* p recebe um espaco como primeiro caractere */ % strcat(p, argv[2]); /* p recebe o padrao propriamente dito */ % strcat(p, " "); /* p recebe um espaco como ultimo caractere */ % strcpy(filename, argv[3]); % m = strlen(p); /* m armazena o tamanho do padrao */ % if (m > MAX_PATTERN_SIZE - 2) { /* valida o tamanho do padrao considerando % a insercao de 2 espacos, antes e depois % do padrao */ % fprintf(stderr, "Tamanho do padrao maior que o maximo permitido\n"); % exit(1); % } % if (k >= m) { % fprintf(stderr, "Numero de erros nao e menor que o tamanho do padrao\n"); % exit(1); % } % % preproc(p, k); % % t = fopen(filename, "r"); % while(fgets(line, MAX_LINE_SIZE, t)) { /* enquanto houver linhas no arquivo */ % line[strlen(line) - 1] = '\0'; % if (Wu_Manber(p, line, k)) { % printf("%s: %s\n", filename, line); % } % } % close(t); %} % %\end{verbatim} %} \end {document}