KMP算法实现
介绍
KMP算法,字符串匹配算法,它与BM算法很相近。假设主串是m,模式串是p。在模式串与主串匹配的过程中,当遇到不可匹配的字符的时候,我们希望找到一些规律,可以将模式串往后多滑动几位,跳过那些肯定不会匹配的情况。
但是大多数情况下,如果主串不是很长,我们会倾向使用BF(朴素)算法,即“暴力匹配”算法,从第一个字符开始,每次滑动一个,完全匹配。
分析
要尽可能多的向右滑动,KMP的算法核心是计算next函数的值,即“好前缀”中所存在的最大公共元素长度,假设模式串的第j位字符与主串的第i位字符不匹配,那么模式串[0, j-1]即为“好前缀”,j位字符成为“坏字符”,通过“好前缀”计算出的最大公共元素长度为k,则,模式串可向右滑动j-k-1位,i不变,继续匹配。
实现
下面是用java实现一个KMP算法:
/** * KMP算法 */ public class KMPTest { /** * KMP匹配算法 * @param m 主串 * @param s 字串 * @return 匹配下标 */ public static int match(char[] m, char[] s){ int i, j, k; i = 0; //主串下标 j = 0; //模式串下标 while (i < m.length) { if (m[i++] == s[j++]) { if (j == s.length) return i - j; continue; } k = next(s, j - 1); j = j - k - 1; } return -1; } /** * 计算next函数的值——求"好前缀"的最大公共字串长度 * @param s 模式串 * @param j 好前缀下标[0, j-1] * @return */ public static int next(char[] s, int j) { int m, n; boolean isEquals; for (m = j-1, n = 1; m > 0 && n < j; m--, n++) { isEquals = true; int a = 0, b = n; while (a < m && b < j) { if (s[a++] != s[b++]) { isEquals = false; break; } } if (isEquals) return m; } return 0; } }