关闭

KMP字符串匹配算法的原理与实现

标签: kmp
1421人阅读 评论(0) 收藏 举报
分类:
Flag Counter

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。

KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。即确定下一次应该从那个位置重新开始匹配。

char*obj = "cbcba";

char*src = "sdcbcbcba";

要在src中寻找obj,过程如下:

从src第0位开始匹配,s匹配失败,移动1位,

从d开始匹配,d匹配失败,移动1位,

接着从src第2位c开始,匹配,继续b,匹配,继续c,匹配,继续b,匹配,继续c,不匹配,

KMP算法关键点就在这里,要移动最大的距离,在这里是2位,即从src第二位移动到第四位,下次从第四位的c开始匹配。

对于一个要查找的目标字符串,每次在哪一位匹配失败后要移动的最大距离可以提前算出来,存到一个数组里,匹配时直接查找就行。


纯粹自己实现,代码有些丑陋,呵呵


// KMP.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

int*kk;
int*kkk;

int KMP(char*src, char*obj)
{
	int k1 = 0; 
	int k2 = 0;
	int len1 = strlen(src);
	int len2 = strlen(obj);
	while (k1 < len1)
	{
		if (src[k1] != obj[0])
		{
			++k1;
			continue;
		}
		while (k2 < len2+1&&k1+k2 < len1+1)
		{
			if (k2 == len2)
				return k1;
			if (src[k1 + k2] == obj[k2])
				++k2;
			else 
				if (kkk[k2] == 1)
				{
				k1 = k1 + kk[k2];
				k2 = 0;
				continue;
				}
				else
					if (obj[k2 - kk[k2]] == src[k1 + k2])
					{
				k1 = k1 + kk[k2];
				k2 = 0;
				continue;
					}
					else
					{
						k1 = k1 + k2 + 1;
						k2 = 0;
						continue;
					}

		}
	}

	return -1;

}


int* shift(char*obj)
{
	int len = strlen(obj);
	kk = new int[len];
	kkk = new int[len];
	for (int i = 0; i < len; i++)
	{
		kkk[i ]= 0; 
	}
	kk[0] = 1;
	if (len > 1)
	{
		if (obj[0] == obj[1])
		{
			kk[1] = 2;
			kkk[1] = 1;
		}
		else
			kk[1] = 1;//条件是src与obj第1位匹配的字符等于obj第0个字符,否则kk[1]=2,这由匹配时的src决定
	}
	

	int k = 2;
	int n = 0;
	int m = 1;
	while (k < len)
	{
		bool flag = false;
		bool flag1 = false;
		while (m<k)
		{
			
			if (obj[m] != obj[n])
			{
				++m;
				continue;
			}
			while (obj[m] == obj[n])
			{
				flag1 = true;
				if (m == k - 1)
				{
					flag = true;
					break;
				}
				++m;
				++n;
			}
			if (flag)
				break;
		}
		if (!flag1)
			if (obj[k] == obj[0])
			{
			kk[k] = k + 1;//此时直接后移,src无需判断
			kkk[k] = 1;
			n = 0;
			m = 1;
			++k;
			continue;
			}
		if (obj[k] == obj[n + 1])
		{
			kk[k] = k + 1;//此时直接后移,src无需判断
			kkk[k] = 1;
			n = 0;
			m = 1;
			++k;
			continue;
		}
		if (flag)
			kk[k] = k - 1 - n;//此处假设src与obj第k位匹配的字符等于obj第n+1个字符,否则kk[k]=k+1,kmp匹配时需做判断
		else
			kk[k] = k;//此处假设src与obj第k位匹配的字符等于obj第0个字符,否则kk[k]=k+1,kmp匹配时需做判断
		n = 0;
		m = 1;
		++k;

	}

	return kk;
}




int _tmain(int argc, _TCHAR* argv[])
{
	//char*obj = "cbcba";
	//char*src = "sdcbcbcba";
	//char*src = "abacaabacabacabaabb";
	//char*obj = "abacab";
	char*src = "BBC ABCDAB ABCDABCDABDE";
	char*obj = "ABCDABD";
	int len = strlen(obj);
	shift(obj);
	for (int i = 0; i < len; i++)
		cout << kk[i] << endl;
	cout << endl;
	for (int i = 0; i < len; i++)
		cout << kkk[i] << endl;
	cout << KMP(src, obj) << endl;
	system("pause");
	return 0;
}



0
0
查看评论

字符串匹配算法KMP详细解释——深入理解

1. 前言  字符串匹配是一个经典算法问题,展开来讲各类问题多达几十种,有名称的算法也不下三十种,所以需要深入学习的东西有很多。这次我们来探讨一个最简单的问题,假设现在随机输入一个长度为m的主串T,另外输入一个长度为n(n≤m)的字符串P,我们来判断字符串P是否是主串T的一个子串(即能否从T中随机取...
  • FX677588
  • FX677588
  • 2016-12-04 16:09
  • 3623

算法——字符串匹配之KMP算法

本节介绍Knuth-Morris-Pratt字符串匹配算法(简称KMP算法)。该算法最主要是构造出模式串pat的前缀和后缀的最大相同字符串长度数组next,和前面介绍的《朴素字符串匹配算法》不同,朴素算法是当遇到不匹配字符时,向后移动一位继续匹配,而KMP算法是当遇到不匹配字符时,不是简单的向后移一...
  • chenhanzhun
  • chenhanzhun
  • 2014-10-09 12:43
  • 2184

字符串模式匹配算法--详解KMP算法

在软考的复习中,看到过几次 字符串的模式匹配算法。看起来挺难的。所以花了点时间查了查关于字符串匹配的算法。下面详细介绍一下KMP模式匹配算法 以及next[j]函数如何计算。
  • zc474235918
  • zc474235918
  • 2014-10-26 10:14
  • 3071

文本的精确匹配(BF,MP,KMP)

一,BF算法 暴力搜索,两重循环 二,MP算法 与BF算法不同的是,每当匹配失败,不必指针回溯,而是利用已经得到的部分匹配结果,将模式字符串滑动若干位置后,继续比较 当失配的情况发生在模式p的第j位: 1,当j=0,则让目标的指针前进一位,模式的起始比较地址回到P0 2,否则,在进行下一轮比较时,目...
  • ccDLlyy
  • ccDLlyy
  • 2016-11-29 21:32
  • 461

KMP算法(字符串匹配算法)之PHP语言实现

KMP算法(模式匹配算法):该算法的关键是求出P0···Pi的最大相同前后缀长度k(部分匹配表): 首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;&quo...
  • dalaoadalaoa
  • dalaoadalaoa
  • 2016-01-30 15:40
  • 1683

KMP字符串匹配算法解析

kmp算法为非常经典的字符串匹配算法。下面先讲解下最原始的字符串匹配方法,也就是暴力求解。时间复杂度为O(m*n) 下面举个例子讲解下暴力大法 如  12314123123b   match为123123 首先从第一个位置str[0]开始依次与match开始进行比较 st...
  • u010485491
  • u010485491
  • 2016-07-26 09:07
  • 581

kmp算法字符串匹配C语言实现

kmp算法字符串匹配 在leetcode做题时,有道题就是写一个strstr函数,先用思路最简单的直接两个循环做,提示时间超过限制。就查了查kmp的资料 翻了下算法导论,感觉像在看数学书,看不太懂,最后还是网上看的博客…… 理解kmp的思路可以看这个http://kb.cnblogs.com/...
  • u013401853
  • u013401853
  • 2016-03-28 21:41
  • 1108

KMP字符串匹配(初学者必看,讲的很清晰)

从头到尾彻底理解KMP 首先声明一下,本博文转自July的博客,之前看了很多关于KMP算法的博客,发现都没讲清楚,但看了July的博客后,我就对KMP算法有了一个很清楚的认识,在这里我要感谢July。转自http://blog.csdn.net/v_july_v/art...
  • luoshengkim
  • luoshengkim
  • 2015-03-29 10:34
  • 3036

KMP算法(字符串匹配算法)详解及java实现

KMP算法是BF(Brute Force)算法的一种改进算法,什么是BF算法这里不多做解释。 1.KMP算法实现思路:   每当一趟匹配过程中出现字符比较不等时,不需要回溯主串上面的指针i,而是利用已经计算出的模式串P在j位置前面的子串P0...Pj-1的部分匹配值k将模式向右滑j-k个字符,...
  • syy0377
  • syy0377
  • 2013-12-16 15:25
  • 4311

史上最浅显易懂的KMP算法讲解:字符串匹配算法

KMP算法是一种改进后的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法)。 KMP算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法。相信很多人初识KMP算法的时候始终是丈二和尚摸不着头脑,要么完...
  • wangbaochu
  • wangbaochu
  • 2016-02-18 20:32
  • 10405
    个人资料
    • 访问:625290次
    • 积分:10540
    • 等级:
    • 排名:第1789名
    • 原创:468篇
    • 转载:61篇
    • 译文:0篇
    • 评论:65条
    最新评论