[小明学算法]6.字符串匹配算法---KMP
1.简介
字符串匹配就是看看那字符串b是不是字符串a的子串.常用的Knuth-Morris-Pratt 算法,又称KMP算法.
2.主要思想
当patter在某一位置与string匹配失败时,我们除了知道从string的这个位置进行匹配失败这个结果外,是否可以从前面的匹配中获得更多的信息呢。即当前匹配点匹配失败之后,向右滑动的距离是可以提前计算出来的.
3.举例
abcabcabcdef --------- string
abcabcdef --------- pattern
KMP就是利用已经匹配了的字符串这个信息,来进行尽可能的向右滑动,避免无谓的比较。匹配字符就是两个字符串的公共部分那么究竟当不匹配的时候,可以向右滑动多远呢?
以上面的pattern "abcabcdef"为例:
当第一个字符不匹配的时候,没有额外信息,那么就向右滑动1个字符。
当第二个字符不匹配的时候,说明之前匹配的字符为a,但是我们是第二个字符不匹配,还是只能向右滑动1个字符。
当第三个字符不匹配的时候,说明之前匹配的字符为ab,那么可以向右滑动2位;
当第四个字符不匹配的时候,说明之前匹配的字符为abc,那么可以向右滑动3位;
当第五个字符不匹配的时候,说明之前匹配的字符为abca,那么也只能向右滑动3位;
。。。。。。
4.关键问题
那么KMP算法的关键问题就是计算pattern某位置匹配失败的时候,可以向右滑动的位数。
下面白话一下如何计算这个滑动位数,0匹配和1匹配时,向右滑动都为1.当匹配数n(n>=2)的时候,在之前匹配的字符串t1中,新增加的字符串t2,且不是t1的23:20:05前端完全重合的字串,则滑动数值加一,否则结束.
5.代码
View Code
static void Main(string[] args) { char[] pattern = { 'a', 'b', 'c', 'a', 'b', 'c', 'd', 'e', 'f' }; int[] table = new int[pattern.Length]; cal_next_table(pattern, table); Console.Read(); } static void cal_next_table(char[] pattern,int[] table) { //设Table[0]为哨兵 table[0] = 1; Print(pattern); Print(table); for (var i = 1; i < pattern.Length; i++) { table[i] = table[i - 1]; //直接与pattern比较了,以免出现t2长度大于t1的情况 //var t1 = GetSubArr(pattern, 0, i); //检测t2(注意起点)是否和t1头部重合,重合则break for(var j=table[i];j<i;j++) { var t2 = GetSubArr(t1, j, i ); Print(t1); if (!strcncmp(pattern, t2)) { table[i]++; } else break; } Print(t1); Print(pattern); Print(table); } } static char[] GetSubArr(char[] pattern,int start,int end) { char[] t = new char[end - start]; for(int i=0;i<t.Length;i++) { t[i] = pattern[i + start]; } return t; } static void Print(Array arr) { foreach(var a in arr) { Console.Write(a + " "); } Console.WriteLine(); } static bool strcncmp(char[] arr1,char[] arr2) { for(var i=0;i<arr2.Length;i++) { if (arr1[i] != arr2[i]) return false; } return true; }
6.结果
a b c a b c d e f 1 0 0 0 0 0 0 0 0 a a b c a b c d e f 1 1 0 0 0 0 0 0 0 b a b a b c a b c d e f 1 1 2 0 0 0 0 0 0 c a b c a b c a b c d e f 1 1 2 3 0 0 0 0 0 a a b c a a b c a b c d e f 1 1 2 3 3 0 0 0 0 a b a b c a b a b c a b c d e f 1 1 2 3 3 3 0 0 0 a b c a b c a b c a b c a b c d e f 1 1 2 3 3 3 3 0 0 a b c d b c d c d d a b c a b c d a b c a b c d e f 1 1 2 3 3 3 3 7 0 e a b c a b c d e a b c a b c d e f 1 1 2 3 3 3 3 7 8
- abcabcdef
- 112333378