KMP字符串匹配算法的优化

Posted 九死九歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP字符串匹配算法的优化相关的知识,希望对你有一定的参考价值。

  KMP算法是什么,我在这里就不做过多赘述了。

  KMP算法的nextval数组中,会有一些重复项。例如:"aaaab"对应的nextval数组是[-1, -1, -1, -1, 3],"114514"对应的nextval数组是[-1, -1, 1, 0, -1, 1]。很明显,字符串中的字符和nextval数组中的数值是映射关系,我们把这个映射叫做nextval映射。

  也就是"aaaab"和"114514"的nextval映射是:‘a’:-1, ‘b’:3和‘1’:-1, ‘4’:1, ‘5’:0。

  其实数组也算是一种映射。我们这里无非就是把数组索引值与数组元素的映射替换成了字符与数组元素之间的映射。

  上代码:

import java.util.HashMap;
import java.util.Map;

public class MyString implements CharSequence 

	public int indexOf(CharSequence that) 

		Map<Character, Integer> nextVal = new HashMap<>();

		int i = -1;
		int j = -2;
		
		/* 获得nextval映射 */
		while (i < that.length() - 1) 
			if (j < 0 || that.charAt(i) == that.charAt(j)) 
				nextVal.putIfAbsent(that.charAt(++i), ++j);
			 else 
				j = nextVal.get(that.charAt(j));
			
		

		// System.out.println(nextVal);

		i = 0;
		j = 0;

		/* 双指针匹配 */
		while (i < this.length() && j < that.length()) 
			if (j < 0 || this.charAt(i) == that.charAt(j)) 
				i++;
				j++;
			 else 
				j = nextVal.get(that.charAt(j));
			
		

		return j > that.length() - 1 ? i - that.length() : -1;

	


  哈希表的插入和查找复杂度都是O(1)。所以这个算法时间复杂度空间复杂度和原来的KMP算法一样。有人可能就说了,你这放着数组不用用散列,重新写个数据结构,开销老大了,这算法写的有够烂的。

  确实,如果说在"1145141919810"中匹配"1919810",我这个算法无论是时间还是空间上都干不过原版的算法。尤其是不带重复的,例如"abcdefgh"中匹配"def",那就更拉胯了。

  但我们想想另一种情况,你有天在网上看到一大段莎翁节选,但是上面没有写出自哪一篇的哪一段。你想知道的话,就得把一大段文字放到上MB的字符串里去匹配。这种情况下,用映射关系的优势就显而易见的出来了。一长段文字放到数组里就是一个庞大的nextval数组,但是放到映射里,算上英文的二十六个字母,甚至空格、标点符号,他的容量也绝对不会超过100个键值对。

  也就是说这个算法的字符串匹配适合于大规模的匹配。

以上是关于KMP字符串匹配算法的优化的主要内容,如果未能解决你的问题,请参考以下文章

C++ 算法进阶系列之从 Brute Force 到 KMP 字符串匹配算法的优化之路

KMP算法

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

kmp算法的个人理解

KMP算法

初识KMP