Última alteração: 25 de Setembro de 2002
Professor: Nivio Ziviani
Monitora: Claudine Santos Badue
2 Trabalho Prático - 30/07/02 - 10 pontos
Data de Entrega: 16/08/02
Penalização por Atraso: 1 ponto até 20/08/02 mais 1 ponto por dia
a seguir
O objetivo deste trabalho é projetar e implementar um sistema de programas para recuperar ocorrências de padrões em arquivos constituídos de documentos, utilizando algoritmos lineares de busca sequencial.
Utilize os arquivos de documentos da coleção TREC disponível
em /export/texto2/wsj, com as seguintes características:
Coleção | Tamanho (Mb) |
wsj88 | 109 |
wsj88_10 | 10 |
wsj88_20 | 20 |
wsj89 | 2.8 |
Um exemplo de registro deste arquivo é:
<DOC>
<DOCNO> WSJ890802-0125 </DOCNO>
<DD> = 890802 </DD>
<AN> 890802-0125. </AN>
<HL> 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 </HL>
<DD> 08/02/89 </DD>
<SO> WALL STREET JOURNAL (J) </SO>
<CO> NCB BPCO TRN EGGS LABOR </CO>
<IN> STOCK MARKET, OFFERINGS (STK)
SECURITIES INDUSTRY (SCR) </IN>
<TEXT>
Even insiders make mistakes.
Sometimes, big, fat, $7 million-dollar mistakes. ...
</TEXT>
</DOC>
Observações:
O que deve ser entregue:
Referências:
Wu, S. and Manber, U. (1992) Fast Text Searching Allowing Errors, Communications of the ACM, pp. 83-91, v. 35(10).
Andrew Hume, Daniel Sunday: Fast String Searching. Software - Practice and Experience 21(11): 1221-1248 (1991).
Daniel Sunday: A Very Fast Substring Search Algorithm. CACM 33(8): 132-142 (1990).
Código:
A seguir é apresentado um código exemplo. Ele faz busca sequencial em textos.
==============================================================================
/*
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 <stdio.h>
/* /// 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);
}
Nivio Ziviani