用c++具体实现的KMP模式匹配算法

2 篇文章 0 订阅
1 篇文章 0 订阅

(原创)用c++具体实现的KMP模式匹配算法

KMP算法

在一个长的字符串中查找子串位置,通过暴力遍历肯定能写出这个匹配字符串的方法,但是效率太过低下。所以有了KMP算法来解决这个问题。

具体KMP的算法概念和理解我是参考了这两篇博客: https://www.cnblogs.com/yjiyjige/p/3263858.html
https://blog.csdn.net/x__1998/article/details/79951598
这两篇博客概念比较清楚了,但是程序拿来用会有些问题,我主要是想写一下关于用c++实现这个算法的具体实现,以及遇到的问题。虽然大部分是比较低级错误,写出来还是希望和我一样的新手在遇到这些问题少走点弯路,也为了让自己加深影响和理解。

KMP算法就是在长的字符串中查找子串的位置,找到就返回其位置下标,未找到就返回-1.具体算法实现就是:先对模式串进行一个next数组计算,计算遇到不匹配时模式串应该跳转到什么位置开始循环(具体理解参考我前面给的博客)。有了这个next数组后,进行KMP算法函数实现,找到就返回其位置下标,未找到就返回-1.这样在查找过程中主串的位置i就不必回溯,节约时间。

程序实现

// 程序头定义
#include<iostream>
#include<string>
using namespace std;

注:从c编程转到c++,尽量用<iostream>替换掉<stdio.h>头文件,还有<string.h>和<string>是一样的。

next函数定义:该函数作用就是, 获得模式串在遇到不匹配的情况,子串的各个位置的应该跳转到哪一个子串位置j开始查找。说明一下,next[0]=-1是为了程序编程方便而给的,在大话数据结构书中是从next[0]=0开始的更好理解,但是编程不方便。

// next数组计算

void get_next(string &T,int *next)
{        int i,j;        
          i=0;                //i是主串位置,j是模式串位置     
          j=-1;             
          next[0]=-1;   
          int tmp=T.size();   //成员函数size和length获得的是无符号型整数
          while(i<tmp)  
          {        
              if (j==-1 || T[i]==T[j]) //T[i]是后缀单个字符,T[j]是前缀单个字符
                    next[++i]=++j;      
              else          
                   j=next[j];   
          }        					//我在这里输出了next数组值
          cout<<next[0]<<next[1]<<next[2]<<next[3]<<next[4]<<next[5]<<endl;
}
// KMP函数定义
int KMP(string &x,string &T)
{    
	int *next=new int[100];        
	int i=0,j=0;        
	get_next(T,next);        
	int tmp1=T.size(),tmp2=x.size();        
	while( i<tmp2 && j<tmp1)        
	{               
		if (j==-1 || x[i]==T[j])              
		{                       
			i++;                       
			j++;               
		}               
		else                       
			j=next[j];        
	}          
	delete[] next;
    	if (j==tmp1)               
        	return i-j;    
	else               
        	return -1;
}

注:我在这里遇到几个问题:(1)是运用string成员函数strlen()、size()和length(),首先strlen(a),这里a必须是char型数组,我这里定义的是string故不行,而size()和length()返回的是unsigned int型,如果放在while(i<T.size())中比较,i是有符号型与无符号型比较会出问题,这个问题我找了好久才找到,略微有点low但是花了我好长时间。
(2)int *next=new int[10];创建一个动态数组,这里的动态数组,动态是指内存可收回,我之前以为动态是指new int[],不用定义数组的大小,这是错的;之前尝试用指针直接传递也是错误的,int *next;只是个int型指针,而且还是没分配内存的野指针。

// 主程序
int main()
{        
	string x="abcababca";        
	string T="cababc";        
	cout<<KMP(x,T)<<endl;        
	return 0;
}

这里主要是用来测试算法正确与否的,主串和子串可以改了尝试。具体程序是这样的,我在vs2005和linux上都跑过,没问题。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值