kmp字符串匹配算法

本文深入探讨了KMP(Knuth-Morris-Pratt)字符串匹配算法,讲解了前缀表的构建过程,并提供了C语言实现代码。通过前缀数组进行查找,有效地避免了不必要的回溯,提高了字符串匹配效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

prefix_table next 数组

GTGTGCF为例子,他的前缀表,前后缀相等的最大长度,不包含本身。

--------------------- -1
G----------------------0
GT---------------------0
GTG--------------------1
GTGT-------------------2
GTGTG------------------3
GTGTGC-----------------0
GTGTGCF-----------------0

整体后移一位


G-------------------- -1
GT---------------------0
GTG--------------------0
GTGT-------------------1
GTGTG------------------2
GTGTGC-----------------3
GTGTGCG----------------0
GTGTGCGF---------------0

得到前缀数组:

G  T  G  T  G  C  G  F
-1 0  0  1  2  3  0  0 

得到过程代码:

void prefix_table(char pattern[],int prefix[], int n){
	prefix[0] = 0;
	int len = 0, i = 1;
	while(i < n){
       
		if(pattern[i] == pattern[len]){
			//prefix[i] = prefix[i-1]+1;  //wrong
            prefix[i] = ++len;
			//len++;
			i++;
		}else{ 
            if(len == 0){
                prefix[i] = 0;
                i++;
            }
			else len = prefix[len-1];
            
		}
	}
	
}
void move_prefix(int prefix[], int n){
    
    for(int i = n-1; i > 0; i--){
        prefix[i] = prefix[i-1];
    }
    prefix[0] = -1;
}

合并一下

void prefix_next(char pattern[], int prefix[], int n){
    prefix[0] = -1;
    prefix[1] = 0;
    int i = 2,len = 0;
    while(i < n){
        if(pattern[i-1] == pattern[len]){
            prefix[i] = ++len;
            i++;
        }else{
            if(len >= 0) len = prefix[len];
            else{
                prefix[i++] = 0;
                len++;
            }
        }
    }
}

查找过程:
定义被查找串txt, 长度m, 查找串pattern, 长度n , 两个指针 i , j 分别指向 两个串。

如果相等,两个指针都后移,如果不相等,那么j = prefix[j]

void kmp_search(char text[], char pattern[]){
    int m = strlen(text);
    int n = strlen(pattern);
    int * prefix = malloc(sizeof(int)*n);
    prefix_next(pattern, prefix, n);
    int i = 0, j= 0;
    while(i < m){
        if(j == n-1 && text[i] == pattern[j]){
            printf("Fount at %d", i-j);
            j = prefix[j];
            i++;
        }
        if(text[i] == pattern[j]){
            i++; j++;
        }else {
            j = prefix[j];
            if(j == -1){
                i++; j++;
            }
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值