Kmp字符串匹配算法

来源:互联网 发布:淘宝高仿鞋店铺名字 编辑:程序博客网 时间:2024/06/03 20:49

上一篇文章,已经讲过了Horspool匹配算法,确实Horspool是一种优秀的算法,它实现了θ(n)的一般效率对文本串的查找,但也有一种算法——Kmp,它也能实现这种效率


先看一下该算法执行的移动过程(即模式串的next数组的值)

先声说明:本人认为该算法在移动值的求法比Horspool不好理解,对于初次接触的人理解会有点难度,不过给予点耐心,还是可以看得懂的

另外下面的 i ,j 变量在下面的函数shiftTable中,请结合理解

未改进:

下标01234567模式串abaabcacnext-10011201

归纳:

其实next的求法就是:1)如果匹配跳动变量j在下表为0时,遍历变量i和匹配跳动变量j都+1,且next[i] = j;

                                    2)匹配跳动变量j 和遍历变量 i 变量所对应字符一样,便利变量i和匹配跳动变量j都+1,且next[i] = j;

                                    3)以上两种情况不满足,则j = next[j],继续和遍历变量i比较


改进:

下标01234567模式串abaabcacnext-10-1102-11       

归纳:其实改进后的算法和为改进相差不是很多,不过时间效率就提高了,就是在第2种情况下,加上:如果遍历变量i和匹配跳动变量j在+1之后在比较,如果两者 = ,那说明i位置不符合时,j位置也不符合,所以只能next[i] = next[j],如下标为2的a next值是-1


先看一下,未改进的shiftTable函数

//求模式串的next数组public int[] shiftTable(char[] m){int[] next = new int[m.length];        int mLen = m.length;//第一个字符next值next[0] = -1;//j在遍历比较过程中会跳动int j = -1;//i为遍历模式串的变量for(int i=0; i<mLen-1;)if(j == -1 || m[i] == m[j]){i++;j++;next[i] = j;}else j = next[j];return next;}



改进后的shiftTable函数

/** * 求模式串的next数组 * @param m *            模式串 * @return */public static int[] shiftTable(char[] m){int mLen = m.length;int[] next = new int[mLen];// 第一个字符next值next[0] = -1;// j在遍历比较过程中会跳动int j = -1;// i为遍历模式串的变量for (int i = 0; i < mLen - 1;)if (j == -1 || m[i] == m[j]){i++;j++;if (m[i] == m[j])next[i] = next[j];elsenext[i] = j;}elsej = next[j];return next;}


在看一下匹配函数

/** * 匹配函数,其中p为模式串,m为模式串长度,t为文本串,n为文本串长度,next为next数组 *  * @param m *            模式串 * @param t *            文本串 * @return */public static int kmp(char[] m, char[] t){int[] next = shiftTable(m);int mLen = m.length;int tLen = t.length;// 遍历文本串n的变量int i = 0;// 表示模式串将验证位置的变量int j = 0;while (i < tLen && j < mLen){// 如果匹配或者j为-1,匹配下一个字符if (j == -1 || t[i] == m[j]){i++;j++;}else{j = next[j];}}if (j == mLen)return i - j;elsereturn -1;}


验证:


// args[0]为模式串,args[1]为文本串public static void main(String args[]){System.out.println(kmp("abaabcac".toCharArray(),"asdfaddsdabaabcacsdws".toCharArray()));}


输入:

args[0]: abaabcac

args[a]: asdfaddsdabaabcacsdws


输出: 9