Conocimiento de cadenas de estructuras de datos, coincidencia de patrones simple, coincidencia de patrones KMP

1. Una serie de conocimientos básicos.

1. Definición de cadena:

String (String) es una secuencia finita de cero o más caracteres, también conocida como cadena.
一般记为:
s="a1a2.......an"(a>=0)

Nota: donde s es el nombre de la cadena, la secuencia de caracteres entre comillas dobles es el valor de la cadena, y las comillas dobles en sí mismas no pertenecen al contenido de la cadena. ai (1 <= i <= n) es un carácter arbitrario, que se llama el elemento de la cadena, y es la unidad básica que constituye la cadena, i es su número de serie en toda la cadena; n es la longitud de la cadena, lo que significa que la cadena contiene El número de caracteres.

2. Cadena de espacio:

Una cadena que contiene solo espacios. La cadena de espacio tiene una longitud, que es diferente de la cadena vacía.

3. Cadena vacía:

Cadena vacía: una cadena de longitud cero se denomina cadena vacía. Puede usar directamente dos comillas dobles para indicar "";

4. Cadena y cadena principal:

Una subsecuencia compuesta de cualquier carácter consecutivo en una cadena se llama una subcadena de la cadena. La cadena que contiene la subcadena es la cadena principal de la subcadena.

5. Comparación de cadenas:

Es similar al uso de strcmp en lenguaje C, usando la codificación ASCII para la comparación.

Dadas dos cadenas: s = "a1a2 ...... an", t = "b1b2 ...... bm", cuando se cumple una de las siguientes condiciones, s <t:

1) n <m, y ai = bi (i = 1, 2, ..., n), donde n representa la longitud de la cadena s y s representa la longitud de la cadena t. Más pequeño que la cadena t significa que la cadena s es menor que la cadena t
2. Hay una cierta k ≤ min (m, n) Esto es cuando k> 1, de modo que ai = bi (i = 1, 2, ..., k-1), ak <bk, si las dos cadenas de la primera Los caracteres comienzan a ser desiguales, es decir, si a1! = B1, solo se compara directamente el tamaño de a1 y b1.

6. La estructura de datos relevante de la cadena:

ADT 串(string)
Data
    串中元素仅由一个字符组成,相邻元素具有前驱和后继关系。
Operation
    StrAssign(T, *chars):        生成一个其值等于字符串常量chars的串T
    StrCopy(T, S):               串S存在,由串S复制得串T
    ClearString(S):              串S存在,将串清空。
    StringEmpty(S):              若串S为空,返回true,否则返回false。
    StrLength(S):                返回串S的元素个数,即串的长度。
    StrCompare(S, T):            若S>T,返回值>0,若S=T,返回0,若S<T,返回值<0。
    Concat(T, S1, S2):           用T返回由S1和S2联接而成的新串。
    SubString(Sub, S, pos, len): 串S存在,1≤pos≤StrLength(S)
                                 且0≤len≤StrLength(S)-pos+1,用Sub返
                                 回串S的第pos个字符起长度为len的子串。
    Index(S, T, pos):            串S和T存在,T是非空串,1≤pos≤StrLength(S)
                                 若主串S中存在和串T值相同的子串,则返回它在主串S中
                                 第pos个字符之后第一次出现的位置,否则返回0。
    Replace(S, T, V):            串S、T和V存在,T是非空串。用V替换主串S中出现的所有
    

2. Almacenamiento de cuerdas

1. Estructura de almacenamiento secuencial:

La estructura de almacenamiento secuencial de la cadena es utilizar un grupo de unidades de almacenamiento de direcciones consecutivas para almacenar la cadena. Asignaremos un área de almacenamiento de longitud fija para la cadena, que generalmente se define mediante una matriz de longitud fija, que es una matriz.

Nota: Cuando definimos una matriz de caracteres en lenguaje C, necesitamos agregar una longitud adicional, porque el compilador agregará automáticamente un '\ 0' para nosotros, de modo que sea conveniente determinar la longitud de su cadena. Pero este '\ 0' no cuenta en la longitud de la cadena.

2. Estructura de almacenamiento en cadena:

Usando listas vinculadas para almacenar cadenas, cada nodo tiene dos campos: uno es el campo de datos (datos) y un campo de puntero (siguiente). Campo de datos (datos): almacena los caracteres en la cadena. Campo de puntero (siguiente): almacena la dirección del nodo posterior.

Nota : Un nodo puede almacenar un carácter o una matriz de caracteres, pero debido a la naturaleza especial de la cadena, el uso del almacenamiento de listas vinculadas como método de almacenamiento de cadenas tampoco es práctico, por lo que se usa menos.

3. Algoritmo de coincidencia de patrones ingenuo

Es atravesar la cadena principal, y luego comparar la cadena que se emparejará con la subcadena, primero hacer coincidir la primera letra de la subcadena que se emparejará con la cadena principal, si la coincidencia es exitosa, las coordenadas de las dos cadenas son a su vez ++, la coincidencia no es Cuando tiene éxito, las coordenadas de la cadena principal vuelven a las coordenadas al comienzo de la coincidencia. Las coordenadas de la cadena que se va a emparejar se borran. Si la coordenada que se va a emparejar es igual a la longitud de la subcadena que se va a emparejar, la coincidencia se demuestra que es exitosa. De lo contrario, se devuelve la primera coordenada de la cadena principal después de la coincidencia; 0 0
int Index(String S,String T,int pos)       //定义了一个主串,子串,开始查找的位置
 {
      int i=pos;      //主串的查找位置,从该位置以后开始查找是否有字串
     int j=1;          //此处不太理解  为啥其实位置是1,感觉应该是0开始的
     while(i<=S[0]&&j<=T[0])
      {  
	if(S[i]==T[j])//判断两个字符串是否相等
 	{
 		 ++i;         //两个相等时自加1,当判断出字串时,j=T的长度+1
 		 ++j;
 	} 
 	else{
 		 i=i-j+2;    //两个字符不相等时,i-j的相当于返回了当前字串开头的那个字母的前一个字符,然后加2,就相当于从主串的下一个字符作为字串开头
 	 	 j=1;       //这时被匹配的字串回到首位
 	      }
 	 }
   if(j>T[0])
 	 return i-T[0];
   else
	return 0;
 }

Pero si se encuentra que una gran cantidad de coincidencias en su cadena principal son desiguales cada vez, entonces vuelva a coincidir. . . . Este ciclo perderá mucho tiempo, por lo que hay un algoritmo de coincidencia de patrones KMP.

3. Coincidencia de patrones KMP

En el algoritmo de coincidencia de patrones ingenuo tradicional, cuando la cadena principal coincide con i, cuando la coincidencia alcanza la posición j, se encuentra una falta de coincidencia, la cadena principal salta de nuevo a la posición i + 1 y la cadena coincidente vuelve a la posición 0. La complejidad del tiempo es alta.

Cuando KMP no coincide con la posición j, la cadena principal no se mueve. La cadena coincidente primero calcula la longitud máxima de cadena coincidente de la subcadena de prefijo y la subcadena de sufijo desde la posición actual. La esencia del algoritmo KMP es encontrar el siguiente proceso.

1. Cómo encontrar la siguiente matriz

Inserte la descripción de la imagen aquí

Inserte la descripción de la imagen aquí
Nota : 1. Según tengo entendido, debe haber caracteres después del prefijo, y el carácter completo no puede ser un prefijo, de manera similar, debe haber caracteres antes del sufijo.

Por ejemplo: si la cadena es "aaaa", el prefijo es "aa" y el sufijo es "aa", no puede ser "aaa"
2. Para la cadena de patrón T, el siguiente [j] representa la subcadena de los primeros j caracteres de T En él, la longitud de la cadena común más larga de su prefijo y sufijo es +1.

El código es el siguiente:

void get_next(char T[], int *next)
{
 
 int i,j;
 i = 1;
 j = 0;
 next[1] = 0;
 while(i < T[0])      //T[0]是子串T的长度
 {       
  //T[i]表示后缀的单个字符
  //T[j]表示前缀的单个字符
  	if( j==0 || T[i] == T[j])    
  	{
  	 ++i;
  	 ++j;
   	next[i] = j;
  	}
  	else
	{
  	 j = next[j];
 	 }
 }
}

El código general de KMP es el siguiente:


 
int Index_KMP(char S[], char T[], int pos)
{
 int i = pos;
 int j = 1;
 int next[255];
 get_next(T, next);
 
 while(i <= S[0] && j <= T[0]){
  //相对于朴素算法,增加了一个j==0的判断
  if( j==0 || S[i] == T[j]){
   ++i;
   ++j;
  }else{
   //j回退到合适的位置,i的值不变
   j = next[j];
  }
 }
 if( j>T[0]){
  return i-T[0];
 }else{
  return 0;
 }
}
10 artículos originales publicados · Me gusta2 · Visitas 217

Supongo que te gusta

Origin blog.csdn.net/dfwef24t5/article/details/105441813
Recomendado
Clasificación