Directorio de artículos
algoritmo kmp
El algoritmo kmp es un algoritmo que compara si str1 (la longitud es n) contiene str2 (la longitud es s).
Pequeños consejos: el método de solución violenta es O (sn), pero mira el siguiente ejemplo:
ayd son diferentes, lo que indica que la cadena no coincide, si esSolución violenta, Se convertirá en lo siguiente.
Empareja de nuevo desde el principio, pero miraalgoritmo kmp¿Qué haremos después?
¿Porqué es eso?
La esencia del algoritmo kmp es comprender las características de su propia búsqueda de cadenas y evitar coincidencias repetidas para acelerar el proceso de algoritmos violentos.
En la figura inicial
Tanto acac como acac se combinan con éxito y la cadena str2 cumple una característica antes de d
A . . . A A ... AA . . . Una
es decir, principio y al final son los mismos (A = ac) (... no =)
Por lo tanto, puede comprender mejor la imagen anterior. Part2 y part3 se han comparado con éxito, y también se comparan part2 y part1 (entendemos las características de str2). Naturalmente, no es necesario comparar part1 y part3. Puede saltar directamente a la siguiente imagen.
Definir las características de la matriz str2-next
La siguiente matriz se refiere a cuando un bit de str1 no coincide con un bit de str2,¿A qué puntero j debería saltar?¿Qué?
Déjame darte algunas escenas, ¿a cuál deberías saltar?
Aquí la cadena antes de d en str2 no cumple con las características de A ... A, así que pase a la siguiente figura
(El puntero J salta a la posición 0, el puntero i no se mueve), luego siguiente [4] = 0 en nuestra siguiente matriz
¿Dónde saltas aquí?
Encontramos que antes de que h en str2 satisfaga las características de A ... A, salte a la siguiente figura
Es decir, el puntero i es diferente, el puntero j salta de la posición 6 a la posición 2, es decir, para esta cadena str2, next [6] = 4
¿Dónde saltas aquí? ? ?
Saltar a la imagen de abajo
(I pointer +1, j pointer no se mueve, aquí definimos la siguiente matriz como -1, es decir, next [0] = - 1)
Mira la siguiente matriz a continuación
- Si el bit 0 no es igual, el puntero i +1, el puntero j no se mueve, se establece en -1
- Si el primer lugar no es igual, mire la cadena antes de c, a, no cumple con las características de A ... A, y el puntero j salta a 0
- Si el segundo dígito no es igual, mire la cadena antes de a, ac, no cumple con las características de A ... A, y el puntero j salta a 0
- Si el tercer dígito no es igual, observe la cadena antes de c, aca, para cumplir con las características de A ... A, y el puntero j salta a la parte posterior de A, es decir, 1
- Si el cuarto dígito no es igual, mire la cadena antes de a, acac, y satisfaga las características de A ... A, el puntero j salta al siguiente dígito de A, que es 2
- Si la quinta posición no es igual, mire la cadena antes de f, acaca, y satisfaga las características de A ... A, el puntero j salta a la parte posterior de A (aca, A se superpone con A), es decir, 3.
- Si el sexto dígito no es igual, mire la cadena antes de g, acacaf, no cumple con las características de A ... A, el puntero j salta a 0
Código
public class main {
//得到next数组
//编写该函数代码是理解如何由next[i-1]得到next[i]
//next[i-1]=t 代表前t位(0~t-1) 等于后面t位(到i-2位)
//因此若s[t]==s[i-1] 则next[i]=t+1
//否则最后一位不等代表不满足A...A的特点,直接为0
public static int[] getnext(String s)
{
int[] next=new int[s.length()];
next[0]=-1;
for(int i=1;i<next.length;i++)
{
if(i==1)
{
next[1]=0;
}
else {
if(s.charAt(next[i-1])==s.charAt(i-1))
{
next[i]=next[i-1]+1;
}
else {
next[i]=0;
}
}
}
return next;
}
public static boolean kmpmatch(String s1,String s2)
{
int[] next=getnext(s2);
int i=0,j=0;
for(;i<s1.length();i++)
{
if(j==s2.length())
{
return true;
}
if(s1.charAt(i)==s2.charAt(j))
{
j+=1;
}
else
{
if(j==0)
{
i=i+1;
}
else {
j=next[j];
}
}
}
return false;
}
public static void main(String[] args)
{
System.out.println(kmpmatch("adaddefg", "ac"));
}
nextval
-
Mejora de la siguiente matriz, fácil de entender
-
La siguiente matriz representa la posición a la que saltará el puntero j. Si siguiente [a] = b, que no es igual a s2 [a], el puntero j salta de a a b. Si s2 [b] == s2 [a ], no esperará, sino que también saltará hacia adelante, por lo que podemos cambiar la siguiente matriz a la posición final del salto, que es nextval
-
Por ejemplo
-
Código
public static int[] getnextval(String s)
{
int[] next=getnext(s);
for(int i=0;i<next.length;i++)
{
if(s.charAt(i)==s.charAt(next[i]))
{
next[i]=next[next[i]];
}
}
return next;
}
aplicaciones kmp
Tema clásico 1: str1: "123456", hay muchas palabras rotativas, "123456", "23456,
" 345612 "... ¿
Determinar si str1 es una palabra rotativa de str2?
Extienda str1 a str1str1, y luego vea si str2 es una subcadena, y use kmp aquí.
Tema clásico 2: Pregunte si tree2 es un
subárbol del árbol 1. Debe estar completo y el subárbol contiene un nodo raíz completo:
Solución violenta:
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x; }
}
public static boolean ischildtree(TreeNode root1,TreeNode root2)
{
if(root1==null||root2==null)
{
return false;
}
if(issametree(root1, root2))
{
return true;
}
return ischildtree(root1.left, root2)||ischildtree(root1.right, root2);
}
public static boolean issametree(TreeNode root1,TreeNode root2)
{
if((root1==null&&root2!=null)||(root1!=null&&root2==null))
{
return false;
}
if(root1==null&&root2==null)
{
return true;
}
if(root1.val==root2.val)
{
return issametree(root1.left, root2.left)&&issametree(root1.right, root2.right);
}
else {
return false;
}
}
La esencia también es una comparación de cadenas, cada árbol se llena en un árbol binario y se almacena en orden de matriz, y luego la "cadena detrás" se usa en el lado opuesto del algoritmo kmp, ¿es la subcadena anterior?