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

原创 2015年07月10日 21:12:07
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;
}



版权声明:

字符串匹配算法(KMP、BM和Sunday),及Python实现

 分类: Python/Ruby 这篇博客主要对三种字符串匹配算法(KMP、BM、Sunday)进行总结。这三种字符串匹配算法之间的主要区别在于:如果在匹配过程中遇到一个不匹配位,该用...

字符串匹配算法 BF/KMP实现/栈、队列

import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.uti...

字符串匹配算法KMP Java实现

kmp算法的核心思想:先对搜索字串生成偏移对照表,匹配时从左向右依次比较(bm从右向左,号称比kmp更快),相等则文档和搜索字串的下标+1迭代,否则查表,定位最优的偏移位置(文档下标不变,搜索字串下标...

字符串匹配算法KMP实现

具体原理参照《算法导论》,这里做了一点小修改。 获取模式值的函数: void getNextVal(int next[], int n, const char *str) { int k = 0; ...

Golang实现的KMP字符串匹配算法

算法的细节可以参考网上的资料或

字符串匹配算法(KMP、BM和Sunday),及Python实现

主要对三种字符串匹配算法(KMP、BM、Sunday)进行总结。这三种字符串匹配算法之间的主要区别在于:如果在匹配过程中遇到一个不匹配位,该用何种策略进行移位。例如,存在两个字符串,如下:   字...

KMP字符串匹配算法实现

kmp字符串匹配算法C++代码实现 #ifndef __H_KMP_H__ #define __H_KMP_H__ #include //获得next数组 int _fill_next_array...

Java实现算法导论中KMP字符串匹配算法

"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。 "部分匹配"的实质是,有时候,字符串头部和尾部会有重...

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

KMP算法是BF(Brute Force)算法的一种改进算法,什么是BF算法这里不多做解释。 1.KMP算法实现思路:   每当一趟匹配过程中出现字符比较不等时,不需要回溯主串上面的指针i,而是...
  • syy0377
  • syy0377
  • 2013年12月16日 15:25
  • 4103

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

KMP算法(模式匹配算法):该算法的关键是求出P0···Pi的最大相同前后缀长度k(部分匹配表): 首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:KMP字符串匹配算法的原理与实现
举报原因:
原因补充:

(最多只允许输入30个字)