数据结构--KMP模式匹配算法

今天,在看数据结构--串这一章节时,看到了KMP算法,相对较复杂些,在此单独做下整理。

kmp算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是根据给定的模式串W1,m,定义一个next函数。next函数包含了模式串本身局部匹配的信息。

例子:

假如我们要比较两个字符串是否相等。

在T串中查找S串。我们用最笨的方法去想,就是将T串与S串中的每一个元素一一去匹配,

如图所示,一旦S串中的一个元素与T串中的元素不匹配,则在T串中向后移动一个位置,再重头进行比较。

通过上图可以想象,最糟糕的情况就是都匹配不到,这样的匹配方式性能很低。

后来我们的前辈们,发现了KMP算法,下面我们来看图。

根据这种思想,可以得出如图步骤

再看一个例子

是否将S串的首字符直接移动到第六个字符呢?

首先,我们先来分析下S串。按照上面图三,

第一步我们先确认S串本身相同的字符,

前三个字符a<>b<>c,

第1、2字符a b 与 第3、4字符a b相等。

第3个字符c与第6个字符x不相等。

第二步,根据第一步结论,看下图,途中我加了坐标,

因为S1 <> S2 <> S3 并且 S1=T1、S2=T2、S3=T3、S4=T4、S5=T5。

所以S1 S2不需要再和T2 T3 T4 T5进行比较(因为你已经知道了,谁和谁是否相等)

S6 <> T6 并且S3 <> S6,所以要比较S3 是否等于 T6,所以就会有下图。

所以No2,应该移动到如上图所示的位置,到此KMP的算法思想就是这样,需要好好领会下。

总结设计思想,我认首先对匹配字符串本身相同字符进行一个记录、其次利用T与S串匹配过的记录进行判断,避免再进行多余的匹配操作。

下面再说下,如果记录匹配字符串本本身相同的字符统计,在数据结构书里叫做next数值推导(根据推导出的每个字符下的数值,当匹配时,此数值不等于被匹配的字符串字符时,按照此数值下的next值,进行位置的移动)

next推导公式:相似字符个数 + 1

package com.test;

public class PM_KMP {
	public static void main(String args[]) {
		//= System.out.println(PM("YEUR7tyu683ghkkl7tyu683gh","l7tyu6"));
		// System.out.println("OK="+PM("abcecabcabcabcc","xcabycab"));
		System.out.println("OK=" + PM("abcabcabcabx", "abcabx"));
		//System.out.println("OK=" + PM("abcecaxcabcabcc", "cabcaa"));
	}

	public static int PM(String T, String P) {// KMP算法
		int[] next = BuildNext(P);// 构造next[]表
		int i = 0;// 主串指针
		int j = 0;// 模式串指针

		while (j < P.length() && i < T.length()) {// 自左向右逐个比较字符

			if (j < 0 || T.charAt(i) == P.charAt(j)) {// 若匹配
				i++;
				j++;// 则转到下一对字符
			} else
				// 否则
				j = next[j];// 模式串右移(注意:主串不用回退)
		}// while

		if (j >= P.length())
			return (i - j);
		else
			return -1;
	}

	protected static int[] BuildNext(String P) {// 建立模式串P的next[]表
		int[] next = new int[P.length()];// next[]表
		int j = 0;
		int t = next[0] = -1;

		while (j < P.length() - 1)
			if (0 > t || P.charAt(j) == P.charAt(t)) {// 匹配
				j++;
				t++;
				next[j] = t;// 此句可以改进...
			} else
				// 失配
				t = next[t];

		return (next);
	}

	protected static int[] BuildNextImproved(String P) {// 建立模式串P的next[]表(改进版本)
		int[] next = new int[P.length()];
		int j = 0;
		int t = next[0] = -1;

		while (j < P.length() - 1)
			if (0 > t || P.charAt(j) == P.charAt(t)) {
				j++;
				t++;
				next[j] = (P.charAt(j) != P.charAt(t)) ? t : next[t];// 注意此句与未改进之前的区别
			} else
				// 失配
				t = next[t];

		return (next);
	}

	protected static void ShowNextTable(// 显示next[]表,供演示分析
			int[] N, int offset, int length) {

		int i;
		for (i = 0; i < offset; i++)
			System.out.print("\t");
		for (i = 0; i < length; i++)
			System.out.print("\t" + N[i]);
		System.out.print("\n\n");
	}

}

数据结构--KMP模式匹配算法,码迷,mamicode.com

时间: 2024-10-19 17:56:30

数据结构--KMP模式匹配算法的相关文章

Java数据结构-串及其应用-KMP模式匹配算法

串(string)是由零个或多个宇符组成的有限序列,又名叫字符串. 定义的解释: ??串中的字符数目n称为串的长度,定义中谈到"有限"是指长度n是一个有限的数值. ??零个字符的串称为空串(null string),它的长度为零,可以直接用两双引号一表示,也可以用希腊Φ字母来表示. ??所谓的序列,说明串的相邻字符之间具有前驱和后继的关系. 下面是串的一些概念性东西: ??空格串,是只包含空格的串.注意它与空串的区别,空格串是有内容有长度的,而且可以不止一个空格. ??子串与主串,串中

朴素和KMP模式匹配算法(Java)

朴素模式匹配算法 public class Test { //朴素模式匹配算法 public int Index(String s,String t,int pos){ int i = pos;//主串中第几个位置开始比较 int j = 0;//模式串中的第一个位置 while(i<s.length()&&j<t.length()){ if(s.charAt(i)==t.charAt(j)){ i++; j++; }else { i = i-j+1;//主串的下一个位置 j

详细解读KMP模式匹配算法

转载请注明出处:http://blog.csdn.net/fightlei/article/details/52712461 首先我们需要了解什么是模式匹配? 子串定位运算又称为模式匹配(Pattern Matching)或串匹配(String Matching).在串匹配中,一般将主串称为目标串,将子串称为模式串.本篇博客统一用S表示目标串,T表示模式串,将从目标串S中查找模式串T的过程称为模式匹配. 虽然我们的主角是KMP模式匹配算法,但我们还是要先从暴力匹配算法讲起,通过发现暴力匹配算法存

改进版KMP模式匹配算法

背景 朴素匹配算法太低效了.冗余过多,已经比较过的,没必要重复:可以从比较结果中推导出来的,也没必要再重复. 核心 主串不回溯,变化要匹配的串的下一次比较的位置. 实现 两个函数,一个提供next数组,即存储要匹配的串的每一个元素匹配失败后,下一次要比较的位置的数组.另一个实现匹配. java代码 public class KMP {//获取next数组private int[] getNext(char[] t_char){int size = t_char.length;int next[]

串-KMP模式匹配算法(nextval数组)

#include <stdio.h> #include <stdlib.h> #include <string.h> void get_next(char T[100],int *next); int Index_KMP(char S[100],char T[100],int pos); int main() { int n; char S[100],T[100]; gets(S); gets(T); n=Index_KMP(S,T,2); printf("%

【数据结构和算法】:KMP模式匹配算法

Knuth-Morris-Pratt 字符串查找算法,简称为 "KMP算法",常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth.Vaughan Pratt.James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法.整个KMP的重点就在于当某一个字符与主串不匹配时,我们应该知道j指针要移动到哪里. 如图:C和D不匹配了,我们要把j移动到哪?显然是第1位,因为如下面蓝框所示,前面A已经匹配. 下面也如此: 可以把j指针移动到第

数据结构(三)串---KMP模式匹配算法之获取next数组

(一)获取模式串T的next数组值 1.回顾 我们所知道的KMP算法next数组的作用 next[j]表示当前模式串T的j下标对目标串S的i值失配时,我们应该使用模式串的下标为next[j]接着去和目标串失配的i值进行匹配 而KMP算法的next求值函数 我们可以知道next除了j=1时,next[1]为0,其他情况都是比较前缀和后缀串的相似度(第三种情况是当相似度为0时,next值为0+1=1) next数组,是用来评判前后缀的相识度,而next值,则是等于相似度加一 2.思考 虽然我们知道是

数据结构(三)串---KMP模式匹配算法实现及优化

KMP算法实现 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 40 typedef int ElemType; typedef int Status; //设置串的存储结构 typede

KMP模式匹配算法:Oulipo

Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book: Tout avait Pair normal, mais tout s’affirmait faux. Tout avait Fair normal,