kmp算法-字符串匹配

kmp算法-字符串匹配

描述

主串为S,模式串为T,指针i和j指示主串S和模式串T中当前正待比较的字符位置。

KMP算法的思想

KMP算法就是从主串中找到与模式串完全匹配的位置。 
从主串的第pos个字符起和模式串的第一个字符比较,若相等,则逐个比较后续字符
;否则每当一趟匹配过程中出现字符不等时,不需回溯i指针,而是利用已经得到的
“部分匹配”结果将模式串向右“滑动”尽可能远的一段距离继续比较。依次类推,
直至模式串中的每个字符依次和主串中的一个连续的字符序列相等,则匹配成功,
函数值为和模式串中第一个字符相等的字符在主串中的序号,否则匹配不成功,函
数值为0。 
KMP算法的最大优点是减少字符串查找过程的回退,i指针不需要回溯。 
模式匹配成功的条件是j>T[0]
匹配成功返回的值是i-T[0] 

KMP算法的流程 

假设主串为's1 s2...sn' ,模式串为'p1 p2...pn' 
令i的初值为pos,j的初值为1,若在匹配过程中si=pj,则i和j分别增1,
否则i不变,而j退到next[j]的位置再比较,若相等,则指针各增1,
否则j再退到下一个next值的位置,依次类推,直至下列两种可能:
1.j退到某个next值s时字符比较相等,则指针各自增1,继续进行匹配
2.j退到值为0(即失配),则此时需将模式继续向右滑动一个位置,即从
主串的下一个字符s(i+1)起和模式串重新开始匹配。 
注:匹配过程中产生“失配”时,指针i不变,指针j退回到next[j]所
指示的位置上重新进行比较,并且当指针j退回到0时指针i和指针j需
同时增1 
next数组=最大公共前后缀个数+1 

代码

#include<stdio.h>
#include<string.h>
int index_KMP(char *s,char *t,int pos); 
//利用模式串的t的next函数求t在主串s中的第pos个位置之后的位置的KMP算法(t非空,1<=pos<=Strlength(s))。
void get_next(char * t,int * next); 
//求模式串t的next函数的并存入数组next[]中。
char s[100];
char t[100];
int next[5];
int pos=0;
int index_KMP(char *s,char *t,int pos){ 
//利用模式串的T的NEXT函数求t在主串s中的第pos个位置之后的位置的KMP算法,(t非空,1<=pos<=Strlength(s)).
    int i=pos,j=1;
    while (i<=(int)strlen(s)&&j<=(int)strlen(t)){
    	if (j==0  ||  s[i]==t[j-1]){//继续进行后续字符串的比较
    		i++; 
            j++;
		}
		else{
			j=next[j]; //模式串向右移动
		}
    }
	if(j>(int)strlen(t)){//匹配成功
		return i-strlen(t)+1;
	}
	else{//匹配不成功 
		return 0;
	}
}
void get_next(char *t,int *next){
//求模式串t的next函数的并存入数组next[]中。
    int i=1,j=0;
    next[0]=next[1]=0;
    while(i<(int)strlen(t)){
    	if(j==0 || t[i]==t[j]){
    		i++; 
            j++; 
            next[i]=j;
		}
		else{
			j=next[j];
		}
    }
}
int main(){
    printf("请输入字符串(主串):");
	gets(s);
	printf("请输入模式串:");
	gets(t);  
    int n; 
    get_next(t,next);
    n=index_KMP(s,t,pos);
    if(n!=0){
    	printf("模式串t在主串s中第%d个位置起开始匹配\n",n);
	}
	else{
		printf("主串中不存在与模式串相匹配的子串\n");
	}
}

结果

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值