字符串匹配-KMP算法

最近在看严蔚敏版的数据结构,看到kmp的时候 折腾了好半天 发现这个版本的跟网上一些博客里的写法不一样,所以写此博客记录一下自己理解的版本。

 

假设有字符串s和p,循环比较s[i]和p[j]是否相等,如果相等,i++,j++,继续比较,如果不相等,kmp则采取的就是i不动,移动j的位置,充分利用p字符串中重复字符集的作用。将j移动到next[j]的位置,将s[i]和p[next[j]]比较,看是否相等,此时有两种情况:

  • 1.相等,则执行i++,j++,继续往后判断;
  • 2.不相等。此时,将j移动到next[next[j]]的位置,继续判断,此时若s[i]==p[next[next[j]]],则到步骤一,否则步骤二,继续往后移动,直到j移到p字符串的开头,说明没有匹配到,此时i++,j++继续往后判断

然后重点就是next数组的求法:

求next数组时候,将匹配字符串p既当做主字符串,又当做模式字符串。过程类似以上循环的步骤。假如一直循环,当s[i]与p[next[m]]相等时,next[j+1] = next[m]+1;

如果一直到开头都匹配不到时,则next[j+1] = 1;

 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int *getNext(char *s,int next[],int len);


//获取next数组
int *getNext(char *s,int next[],int len){
    int k=0,j;
    next[0] = -1;
    next[1] = 0;  //由定义  next[0]=1
    for(j= 2;j<len+1;j++){
        k = next[j-1];
        while(k>0 && s[j-2] != s[k-1]){
            k = next[k];
        }
        if(s[j-2] == s[k-1]){
            next[j] = k+1;
        }else
        next[j] = 1;

    }
    return next;

}



int main(){

//    char string[]="asdabaadcdabbaabc";
//    char mat[] = "adcd";
//    char *s = string;
//    char *m = mat;
	char *string= (char *)malloc(sizeof(char));
	char *mat = (char *)malloc(sizeof(char));
    int i=0,j=1,q,k;
    int len_mat;
    int len_str;
    int count = 0;
    int *next;
    scanf("%s",string);
    scanf("%s",mat);
    len_mat = strlen(mat);
    len_str = strlen(string);
    next = (int *)malloc((len_mat+1)*sizeof(int));
    next = getNext(mat,next,len_mat);
    for(i = 0;i<len_str;i++){
	    	if(string[i] != mat[j-1])
	    		count = 0;
			while(string[i] != mat[j-1] && j>0)
	    	{
	    		j = next[j];
	    		}
			if(string[i] == mat[j-1])
			{
				count++;
				j++;
				}
			if(j == 0){
				j = 1;
			}
			if(count == len_mat){
				printf("%d\n",i-len_mat+2);
				count = 0; 
				j = 1;
				i--;
			}
		}
        if(count == len_mat){
            printf("match:  %d   %d\n",i-len_mat+1,i);
        }else{
            printf("not match!\n");
        }



		for(i = 1;i<len_mat+1;i++)
		printf("%d ",next[i]);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值