`
543089122
  • 浏览: 153205 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

字符匹配算法(KMP)

阅读更多
package sunfa.kmp;

/**
 * 朴素字符串匹配算法
 */
public class SimpleKMP {
	public static void main(String[] args) {
		int index = simpleKmp("12444abababab", "444ababab");
		System.out.println(index);
	}

	/**
	 * 朴素字符串匹配算法的一个特点是主字符串指针要回溯
	 * 性能o((n-m+1)m)
	 * @param src
	 * @param dect
	 * @return
	 */
	private static int simpleKmp(String src, String dect) {
		if (dect.length() > src.length())
			return -1;
		char[] srcArr = src.toCharArray();
		char[] dectArr = dect.toCharArray();
		for (int i = 0; i < srcArr.length; i++)
			if ((i + dect.length()) <= srcArr.length
					&& comp(srcArr, dectArr, i, i + dect.length()))
				return i;
		return -1;
	}

	private static boolean comp(char[] srcArr, char[] dectArr, int a0, int a1) {
		int j = 0;
		for (int i = a0; i < a1; i++)
			if (srcArr[i] != dectArr[j++])
				return false;
		return true;
	}
}



package sunfa.kmp;

import java.util.Arrays;

/**
 * 这个算法比较靠谱,而且看的懂 KMP算法分2步:
 * <p>
 * ①根据子字符串得到next数组
 * <p>
 * ②子串与主串进行朴素比较,但是匹配不上的时候就查找next数组。
 * 以前在这个时候是i回溯并且j=0,kmp算法是i不动并且j回溯(根据next数组进行回缩,
 * 找到那个能够匹配上的地方。它怎么知道哪个地方能够匹配的上呢,看看next数组的实现就清楚了。)
 * 
 * next数组的实现:对子串进行迭代,每次取p.substring(0, i)个字符,然后把该字符劈成两半并且比较左半边和右半边是否相等,
 * 如果相等则将两半处的索引n加到next数组中去
 * <p>
 * 
 *
 * /**
 * kmp算法 一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此称之为KMP算法。此算法可以在O
 * (n+m
 * )的时间数量级上完成串的模式匹配操作,其基本思想是:每当匹配过程中出现字符串比较不等时,不需回溯指针,而是利用已经得到的“部分匹配”结果将模式向右“
 * 滑动”尽可能远的一段距离,继续进行比较。 参考http://www.iteye.com/topic/501047
 * 
 * KMP算法的思路: 
 * http://iaiai.iteye.com/blog/1140796
 * 
 */
 */
public class KMP {

	String s; // 主字符串
	String p; // 匹配字符串
	int[] next; // 匹配字符串的next数组

	int times; // 记录匹配的次数
	int index; // 记录查找到的位置

	/**
	 * 构造函数,初始化各个成员变量
	 * 
	 * @param s
	 * @param p
	 */
	KMP(String s, String p) {
		this.s = s;
		this.p = p;
		this.next = new int[p.length()];
		for (int i = 0; i < p.length(); i++) {
			if (i == 0) {
				this.next[i] = -1;
			} else if (i == 1) {
				this.next[i] = 0;
			} else {
				// 对某个位置之前的字符串考察其开始部分和结尾部分是否相同
				this.next[i] = next(p.substring(0, i));
			}
		}

		this.times = 0;
		this.index = -1;
	}

	/**
	 * 返回子字符串,开始部分和结尾部分相同的情况下的开始部分的下一个位置,即next值
	 * 
	 * @param p
	 * @return
	 */
	private int next(String p) {
		int length = p.length() / 2;

		while (length > 0) {
			if (p.substring(0, length).compareTo(
					p.substring((p.length() - length), p.length())) == 0) {
				System.out.println(p + "<" + p.substring(0, length) + "="
						+ p.substring((p.length() - length), p.length()));
				return length;
			}
			length--;
		}
		return length;
	}

	/**
	 * 对主字符串进行比较,碰到不匹配,查询next数组;如果新元素和当前不匹配元素相同,则继续next
	 * 
	 * @return
	 */
	boolean match() {
		int i = 0;// 主串索引
		int j = 0;// 子串索引
		int index = -1; // index记录匹配的位置

		while (i < this.s.length() && j < this.p.length()) {
			if (this.s.charAt(i) == this.p.charAt(j)) {// 1、按照朴素模式进行匹配
				if (j == 0) {
					index = i;
				}

				i++;
				j++;
			} else {
				// 一直寻找next,直到和当前元素不相等的元素,将其下标赋值给j
				int newj = this.next[j];// 2、当匹配不上了的时候i不用回溯,只需要根据j的索引去查找next数组
				System.out.print("debug[");
				while ((newj != -1)
						&& (this.p.charAt(newj) == this.p.charAt(j))) {
					// newj回溯
					newj = this.next[newj];

					System.out.print("newj:" + newj + ",i:" + i + ",j:" + j
							+ ",v:" + this.p.charAt(j) + ",next:"
							+ Arrays.toString(next) + ",p:" + p);
				}
				System.out.println("]");

				j = newj;

				if (j == -1) {
					i++;// 主串索引++
					j = 0;// 子串索引重置
				} else {
					index = i - j;
				}
			}
			this.times++;
		}

		if (j == this.p.length()) {
			this.index = index;
			return true;
		} else {
			return false;
		}
	}

	public static void main(String[] args) {
		String s = "1ababcababd1ababcababc_def";
		String p = "ababcababc";
		KMP m = new KMP(s, p);

		// 顺便打印next数组;
		for (int i = 0; i < m.next.length; i++) {
			System.out.print(m.next[i] + ",");
		}
		System.out.println();

		if (m.match()) {
			System.out.println("match");
			System.out.println("match times: " + m.times);
			int index = m.index;
			System.out.println(index);
		} else {
			System.out.println("not match");
		}
	}

}

分享到:
评论

相关推荐

    KMP字符串匹配算法

    **KMP字符串匹配算法详解** KMP(Knuth-Morris-Pratt)字符串匹配算法是由D.E. Knuth、V.J. Morris和J.H. Pratt三位学者于1977年提出的,它是一种高效的字符串搜索算法,主要用于在一个主串(text)中查找是否存在...

    字符串的模式匹配算法——KMP

    字符串的模式匹配算法在计算机科学中占据着重要的地位,它主要应用于文本搜索、数据分析和文本处理等领域。KMP(Knuth-Morris-Pratt)算法是其中一种高效的算法,尤其适用于处理具有重复子串的模式匹配问题。接下来...

    KMP中文字符匹配算法的C++实现

    对于中文字符匹配,我们需要注意编码问题,因为中文字符通常采用UTF-8或GBK等多字节编码。 在C++中实现KMP算法,首先需要处理输入的字符串。由于C++标准库中的`std::string`通常存储的是ASCII字符,所以我们可能...

    带通配符的字符串匹配算法

    带通配符的字符串匹配算法则是这个领域的延伸,它允许在模式字符串中包含特殊字符,如星号(*)或问号(?),以表示任意字符或单个任意字符。这种算法使得搜索更加灵活,可以适应更复杂的查询需求。 **通配符的含义** -...

    字符串匹配KMP算法

    字符串匹配 KMP算法

    算法与数据结构 算法分析课程 第11章 字符串匹配 字符串匹配算法 KMP算法 共11页.pptx

    本章节将重点介绍字符串匹配的基本概念以及两种重要的算法——简单字符串匹配算法和KMP算法。 #### 一、简单字符串匹配算法 简单字符串匹配算法是最基础的一种方法,其基本思想是从文本串的第一个字符开始,逐个...

    经典字符串匹配算法KMP匹配

    最经典的KMP算法,VC工程下的源码,便于初学者学习,理解该算法

    KMP字符串模式匹配算法ppt

    KMP(Knuth-Morris-Pratt)字符串模式匹配算法是一种高效的字符串搜索算法,由D.M. Knuth、V. Morris和J.H. Pratt在1970年提出。该算法避免了简单匹配算法中的不必要的回溯,显著提高了在文本字符串中查找模式字符串...

    字符串匹配算法KMP算法

    KMP算法避免了在模式匹配过程中不必要的字符比较,通过构建一个预处理的“next”数组来指导匹配过程,从而提高了效率。 在KMP算法中,主要有两个关键步骤: 1. 预处理阶段:构建“next”数组 这个阶段是KMP算法的...

    模式匹配的KMP算法

    模式匹配的KMP算法是一种高效、可靠的串模式匹配算法,具有广泛的应用前景。本课程设计旨在通过模式匹配的KMP算法的设计和实现,帮助学生深入了解数据结构、算法设计、程序实现等知识点,并提高学生的编程能力和问题...

    KMP_字符串模式匹配算法

    **KMP字符串模式匹配算法详解** KMP(Knuth-Morris-Pratt)算法是一种高效地在主串(text)中查找子串(pattern)的字符串模式匹配算法,由Dijkstra、Morris和Pratt在1970年提出。这个算法避免了不必要的字符比较,...

    字符串匹配的KMP算法.rar_KMP_KMP算法_kmp 字符串匹配_字符串匹配_文件

    - 主串与模式串匹配:从主串S的起始位置和模式串P的起始位置开始比较,如果当前字符匹配,则移动主串和模式串的指针;若不匹配,则根据部分匹配表确定模式串的下一个位置,继续比较,直到找到匹配或模式串遍历完。 ...

    字符串匹配的KMP算法浅析

    KMP算法,全称Knuth-Morris-Pratt算法,是一种高效的字符串匹配算法,主要用于在一个文本字符串S内查找一个词W的出现位置。该算法由Donald Knuth、Vaughan Pratt和James H. Morris发明,因此得名。KMP算法的核心在于...

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

    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的...

    文学研究助手(字符串的查找\模式匹配\KMP算法)

    《文学研究助手——深入解析KMP算法在字符串查找与模式匹配中的应用》 在文学研究领域,高效地处理文本信息是至关重要的。本项目“文学研究助手”正是为解决这一问题而设计,它利用C语言实现,核心算法是著名的KMP...

    字符串匹配的KMP算法

    KMP算法,全称为克努斯-莫里斯-普拉特算法,是一种高效解决字符串匹配问题的算法。在计算机科学中,字符串匹配是指在主文本...KMP算法在文本处理、数据搜索等领域有广泛的应用,是字符串匹配算法中的一种经典解决方案。

    KMP字符串模式匹配算法

    KMP字符串模式匹配算法是一种高效的字符串搜索算法,由D.E.Knuth、V.R.Morris和J.W.Pratt三位学者提出,因此得名KMP算法。该算法避免了在匹配过程中不必要的字符回溯,提高了匹配效率。下面我们将深入探讨KMP算法的...

    字符串匹配KMP算法讲解

    KMP算法是一种高效的字符串匹配算法,由D.E.Knuth、V.R.Pratt和J.H.Morris三位学者共同提出,其核心思想在于利用已有的部分匹配信息避免在比较过程中不必要的回溯,从而提高效率。在传统的字符串匹配算法中,当主串S...

    KMP字符匹配算法

    **KMP字符匹配算法** KMP(Knuth-Morris-Pratt)算法是一种在文本串中查找模式串的高效字符串匹配算法,由唐纳德·克努斯、斯特兰·莫里斯和理查德·普拉特在1977年提出。它避免了不必要的回溯,大大提高了匹配效率...

    kmp模式匹配算法

    KMP(Knuth-Morris-Pratt)模式匹配算法是一种在主串(目标字符串)中查找子串(模式字符串)的高效算法,由D.E. Knuth、V.R. Morris和J.H. Pratt于1977年提出。相较于简单的暴力匹配方法,KMP算法在模式匹配过程中...

Global site tag (gtag.js) - Google Analytics