Tabla de contenido
La operación de posicionamiento de una subcadena generalmente se denomina coincidencia de patrones de cadena.
Algoritmo ingenuo de coincidencia de patrones
- Utilice cada carácter de la cadena principal como el comienzo de la subcadena para que coincida con la cadena que se va a buscar.
- Haga un bucle grande para la cadena principal y comience un bucle pequeño con la longitud de la subcadena al comienzo de cada carácter hasta que la coincidencia sea exitosa o se complete todo el recorrido.
/*返回子串T在主串s中第pos个字符之后的位置。若不存在,则函数返回值为0。*/
/*T非空,1≤pos ≤StrLength(S)。*/
int Index(String S, String T, int pos)
{
int i = pos;/*i用于主串S中当前位置下标,若pos不为1*/
/*则从pos 位置开始匹配*/
int j = 1; /*j用于子串T中当前位置下标值*/
while(i <= S[0] && j <= T[0])/*若i小于S长度且j小于T的长度时循环*/
{
if(S[i] == T[j]) /*两字母相等则继续*/
{
++i;
++j;
}
else /*指针后退重新开始匹配*/
{
i = i-j+2; /*i退回到上次匹配首位的下一位*/
//串是从 1 开始计数的
//i-j+1 恰好回到这次匹配的第一个字符
//所以 (i-j+1)+1 指到下一个字符
//从而开始一轮新的匹配
j = 1;
}
}
if(j > T[0]){
return i-T[0];
}
else
{
return 0;
}
}
Complejidad del tiempo: O (n*m)
Lleva demasiado tiempo y generalmente no se recomienda.
Algoritmo de coincidencia de patrones KMP
Hay tres predecesores, DEKnuth, JHMorris y VRPratt (Knuth y Pratt investigados conjuntamente, investigación independiente de Morris) publicaron un algoritmo de coincidencia de patrones, que puede evitar en gran medida la situación de recorrido repetido, lo llamamos Algoritmo especial Knuth-Morris-Pratt , referido como algoritmo KMP .
En el algoritmo KMP, solo la posición de la subcadena necesita cambiar hacia adelante y hacia atrás, y la cadena principal se mueve hacia atrás.
- Algunos dígitos de la cadena que se va a hacer coincidir no son iguales entre sí y tienen subcadenas correspondientes en la cadena principal. Cuando el último dígito no coincide, estos dígitos en la cadena que se va a hacer coincidir no necesitan ser obviamente desiguales entre sí. en la cadena principal los caracteres a comparar;
- Hay igualdad de palíndromos en la cadena que se va a comparar y tienen subcadenas correspondientes en la cadena principal. Cuando el último dígito no coincide, los primeros dígitos de la cadena palíndromo en la cadena que se va a comparar no necesitan ser obviamente iguales a sí mismos. en los caracteres de la cadena principal para comparar.
- Consumo de tiempo muy reducido, suComplejidad del tiempo O (n+m);
Encuentre la posición de retroceso de una subcadena:
/*通过计算返回子串T的next数组。*/
void get_next(String T, int *next)
{
int i,j;
i = 1;
j = 0;
next[1] = 0;
while(i < T[0]) /*此处T[0]表示串T的长度*/
if(j == 0 || T[i] == T[j])/*T[i]表示后缓的单个字符,*/
/* T[j]表示前缀的单个字符 */
{
++i;
++j;
next[i]=j;
}
else
{
j= next[j];/* 若字符不相同,则j值回溯*/
}
}
codigo maestro
// 返回子串T在主串S中第pos个字符之后的位置。
// 若不存在,则函数返回值为0
// T非空,1<=pos<=StrLength(S)
int Index_KMP(String S, String T, int pos){
// i 用于主串S当前位置下标值,若pos不为1,则从pos位置开始匹配
int i = pos;
int j = 1;//j 用于子串T中当前位置下标值
int next[255];// 定义next数组
get_next(T,next);// 对串T作分析,得到next数组
// 若i小于S的长度且j小于T的长度时,循环继续
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;
}
}
Adjunto:
Respecto a la mejora de encontrar la siguiente matriz :
// 求模式串T的next函数修正值并存入数组nextval
void get_nextval(String T,int *nextval){
int i,j;
i = 1;
j = 0;
nextval[1] = 0;
while(i < T[0]){
if(j == 0 || T[i] == T[j]){
i++;
j++;
if(T[i] != T[j])// 若当前字符与前缀字符不同
{
nextval[i] = j;// 则当前的j为nextval在i位置的值
}
else
{
nextval[i] = nextval[j];
//如果与前缀字符相同,则将前缀字符的nextval值赋值给nextval在i位置的值
}
}
else
{
//若字符不相同,则j值回溯
j=nextval[j];
}
}
}
Si realmente no puedes entenderlo, ¡memorízalo!