经典查找算法 - KMP

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。


package com.sjyttkl.algorithm;

import java.util.Arrays;

/**
 * Java实现KMP算法
 * 
 * 思想:每当一趟匹配过程中出现字符比较不等,不需要回溯i指针, 而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远 的一段距离后,继续进行比较。
 * 
 * 时间复杂度O(n+m)
 * 
 * @author xiaodong
 * 
 */
public class KMP
{
	public static void main(String[] args)
	{
		String str = "ababcabcacbab";
		char[] str_chars = str.toCharArray();
		String pattern = "abcac";
		char[] pattern_chars = pattern.toCharArray();
		int[] next = new int[pattern_chars.length];
		getNext(pattern_chars, next);
		System.out.println("next --->" + Arrays.toString(next));// next --->[-1,
																// 0, 0, 1, 1,
																// 2, 0, 0]
		int result = Kmp(str_chars, pattern_chars, next);
		System.out.println(result);

	}

	private static int Kmp(char[] str_chars, char[] pattern_chars, int[] next)
	{
		int i = 0;
		int j = 0;
		while (i <= str_chars.length - 1 && j <= pattern_chars.length - 1)
		{
			if (j == -1 || str_chars[i] == pattern_chars[j])
			{
				i++;
				j++;
			} else
			{
				j = next[j];
			}
		}
		if (j < pattern_chars.length)
		{
			return -1;
		} else
		{
			return i - pattern_chars.length; // 返回模式串在主串中的头下标
		}
	}

	private static void getNext(char[] chars, int[] next)
	{
		int i = 0;
		int j = -1;
		next[0] = -1;
		// abcac
		while (i < next.length - 1) // 这里不能忘记要-1否则会出现错误
		{
			if (j == -1 || chars[i] == chars[j])
			{
				++i;
				++j;
				//下面的这一对 if--else 是对传统的kmp进行改进的, 下面的 1 和2,取一个就行了
				//1,
				if (chars[i] != chars[j])
				{
					next[i] = j;
				} else
				{
					next[i] = next[j];
				}
				//2,
				//next[i] = j;

			} else
			{
				j = next[j];
			}
		}

	}

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Terry_dong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值