Procesado de cadenas de caracteres 1) Algoritmo Trivial 2) Algoritmo Rabin-Karp. 3) Algoritmo Knuth-Morris-Pratt 4) Algoritmo Boyer-Moore 5) Busqueda de expresiones regulares Problema: Encontrar todas las ocurrencias de un patrón (subcadena) en una cadena de caracteres. Sea T[1..n] una cadena de caracteres de longitud n y P[1..m] el patrón Ejemplo: T= aabbdaabcdad P= aabc a a b b d a a b c d a d Ejemplo: T= aabbdaabcdad P= aabc a a b b d a a b c d a d Ejemplo: T= aabbdaabcdad P= aabc a a b b d a a b c d a d Ejemplo: T= aabbdaabcdad P= aabc a a b b d a a b c d a d Ejemplo: T= aabbdaabcdad P= aabc a a b b d a a b c d a d Ejemplo: T= aabbdaabcdad P= aabc a a b b d a a b c d a d función buscar_trivial (T,P Σ∗): Ν; i:=1; repetir j:=1; k:=i; mientras (Tk=Pj) and (j<=|P|) hacer k:=k+1; j:=j+1; fmientras i:=i+1; hasta (i>(|T|-|P|)) or (j>|P|) si j>|P| entonces devuelve (i-1) sino devuelve (0) fin Coste temporal: O(|T|x|P|) función buscar_PD(T,P Σ∗): N; var Tabla: matriz [0..|P|, 0..|T| de N; para j:=0 hasta |P| hacer tabla[j,0:=j; fpara; i:=0; mientras (i<=|T|) and (tabla[|P|,i 0) hacer tabla[0,i:=0; para j:=0 hasta |P| hacer tabla[j,i:=min{tabla[j-1,i, tabla[j,i-1, tabla[j-1,i-1+δ(Pj,Ti)} fpara i:=i+1; fmientras si (i>|T|) entonces devuelve 0 sino devuelve i fsi fin Coste temporal: O(|P|x|T|) 4 3 a 2 a 2 2 b b 2 3 d a 2 a 1 0 b c 1 d 2 a 3 d Τ= acdabpdqd P= abcd d 4 3 2 1 3 2 2 1 2 3 c b a 3 2 1 0 2 1 0 0 1 1 1 0 2 2 1 0 2 1 0 0 1 0 0 0 1 1 1 0 2 2 1 0 3 2 1 0 3 2 1 0 a c d a b p d q d d 4 3 2 1 3 2 2 1 2 3 c b a 3 2 1 0 2 1 0 0 1 1 1 0 2 2 1 0 2 1 0 0 1 0 0 0 1 1 1 0 2 2 1 0 3 2 1 0 3 2 1 0 a c d a b p d q d función buscar_error(P,T,k):conjunto de N; tabla=vector[0..|P|] de N; f:=k+1; encontrados:= para i:=0 hasta |P| hacer para i:=1 hasta f hacer {tabla[i-1]+1, tabla[i]+1, d+1} d:=tabla[i]; tabla[i]:=e; mientras (tabla[f]>k) hacer f:=f-1 si (f=|P|) entonces insertar(encontrados,j) sino f:=f+1 devuelve encontrados Algoritmo de Knuth-Morris-Pratt f f Α f Β f Α Β C Β f f Construccion de las función FALLO: Trazar un arco desde el estado i al estado j tal que: 2) Los primeros j-1 caracteres del P son iguales que los j-1 caracteres que preceden a i. 1 p2 …pj-1 = pi-(j-1) …pi-1 3) j es el mayor número que satisface 1) y 2) f f f Α f Β f Α Β f Α Β f f Ejemplo de alineamiento: A B A B A B X…….. ABABABCB C Β f f f Α f Β f Α Β f Α Β f f Ejemplo de alineamiento: A B A B A B X…….. ABABABCB C Β función KMP(T,P:Σ∗): N; var f:vector[1..|P|] de N; f:=FF(P); i:=1; j:=1 mientras i<=|T| hacer mientras j<>0 and Pj<>Ti hacer j:=f(j) fmientras si j=|P| entonces devuelve (i-|P|) función FF(P:Σ∗): vector de N; var f: vector de N; f[1]:=0; i:=2 mientras i<=|P| hacer j:=f[i-1]; mientras j<>0 and Pj<>Pi-1 hacer j:=f[j ] fmientras f[i]:=j+1; i:=i+1 fmientras devuelve f fin 3) Algoritmo de Boyer-Moore P1 ….……………….Pm T1 ..…Tk-m+1 ……...…….….Tk………….Tn Tipos de desplazamiento: a) Si Pm no coincide con Tk entonces desplazamos el patrón de forma que alineamos con la ocurrencia más a la derecha del símbolo en P. Supongamos que g es la posición en que aparece el símbolo 1 ….………………… Pm-g ………..Pm T1 ..…Tk-m+g+1 ……...…….….Tk………… .Tk+g ………..….Tn Ejemplo: P= abdbcdabbcb T= abcbbdabcbdcbabxcabcbbcababcbb Ejemplo: P= abdbcdabbcb T= abcbbdabcbdcbabxcabcbbcababcbb Ejemplo: P= abdbcdabbcb abcbbdabcbdcbabxcabcbbcababcbb b) Suponer que los últimos m-i caracteres del patrón coinciden con los últimos m-i caracteres de la cadena T, acabando en la posición k. i+1 … ……..Pm= Tk-m+i+1 …….….Tk Supongamos que Pi<> Tk-m+i b1) Si la ocurrencia más a la derecha del carácter k-m+i en el patrón P es Pg entonces, como en el caso anterior, desplazamos el patrón g posiciones hacia la derecha, de modo que se alinea Pi-g<> Tk-m+i y se comienza de nuevo a comparar m con Tk+g . P1 ….………………… Pi-g ………..Pm T1 ..….Tk-m+g+1 ……...…….….Tk-m+i…….. .Tk+g ………..….Tn b2) Si el sufijo Pi+1 … ……..Pm aparece repetidamente en el patrón en las posiciones Pi+1-g … ……..Pm-g , y Pi<>Pi-g entonces desplazamos el patrón alineando 1 ….………..Pi+1-g …… Pm-g …..…...Pm T1 ..….Tk-m+g+1 ……...Tk-m+i+1…..Tk…….…...Tk+g ………..….Tn Función Boyer-Moore (T,P: Σ∗): Ν; j:=|P|; mientras j<=|T| hacer i:=|P|; mientras i>0 and Pi=Tj hacer i:=i-1; j:=j-1; fmientras si i=0 entonces devuelve j+1 sino j:=j+ max{d1[Tj], d2[i]} fsi fmientras fin Calculo de d1: Para todo carácter c, d1[c] es el i más grande tal que c=Pi, o d1[c] =m si el carácter no aparece en P. Esta tabla cubre las casos a) y b1). Calculo de d2: Para todo i, 1<=i<=|P|, d2[i] proporciona el mínimo desplazamiento g tal que cuando se alinea m sobre Tk+g , el substring Pi+1-g …… Pm-g del patrón coincide con el substring Tk-m+g+1 ……...Tk-m+i+1…..Tk de la cadena T. 4) Algoritmo de Karp-Rabin Se basa en la aplicación de una función de se le asigna un número. 1 …… Pm )<>h(Tk…..Tk+m-1 ) entonces no aparece el patrón en esa …… Pm )=h(Tk…..Tk+m-1 ) entonces es posible que esa subcadena corresponda con el patrón pero hay que comprobarlo carácter a carácter. 1 operación módulo q, siendo q un número primo grande. Por simplicidad supongamos que los símbolos posibles son los dígitos. El k…..Tk+m-1 xk= Tk.bm-1+ Tk+1.bm-2 ……..Tk+m-1 Ejemplo: Si la cadena es ‘1234’ el número k+1 se puede calcular como: xk+1 = (xk -Tk.bm-1)b+ Tk+m sería: /*m=|P|*/ Ejemplo: Supongamos que m=4 314152 x1=31415 314152 x2= 10(31415-10000.3)+2=14152 Función Boyer-Moore (T,P: Σ∗): Ν; m:=|P|; n:=|T|; d:= bm-1 mod q; h(P):= (P1 bm-1 +P2 bm-2 +…+P2)mod q; h(T):=(T1 bm-1 +T2 bm-2 +…+T2)mod q; para k:=1 hasta n-m+1 hacer si h(P)=h(T) y (P1 …… Pm =Tk…..Tk+m-1) entonces devuelve k fsi; h(T):=(h(T)+b.q-Tk.d) mod q h(T):=(h(T) .b+Tk+m) mod q k:=k+1 fpara fin