Kmp字符串匹配算法
2013-09-28 23:02
253 查看
上一篇文章,已经讲过了Horspool匹配算法,确实Horspool是一种优秀的算法,它实现了θ(n)的一般效率对文本串的查找,但也有一种算法——Kmp,它也能实现这种效率
先看一下该算法执行的移动过程(即模式串的next数组的值)
先声说明:本人认为该算法在移动值的求法比Horspool不好理解,对于初次接触的人理解会有点难度,不过给予点耐心,还是可以看得懂的
另外下面的 i ,j 变量在下面的函数shiftTable中,请结合理解
未改进:
归纳:
其实next的求法就是:1)如果匹配跳动变量j在下表为0时,遍历变量i和匹配跳动变量j都+1,且next[i] = j;
2)匹配跳动变量j 和遍历变量 i 变量所对应字符一样,便利变量i和匹配跳动变量j都+1,且next[i] = j;
3)以上两种情况不满足,则j = next[j],继续和遍历变量i比较
改进:
归纳:其实改进后的算法和为改进相差不是很多,不过时间效率就提高了,就是在第2种情况下,加上:如果遍历变量i和匹配跳动变量j在+1之后在比较,如果两者 = ,那说明i位置不符合时,j位置也不符合,所以只能next[i] = next[j],如下标为2的a next值是-1
先看一下,未改进的shiftTable函数
改进后的shiftTable函数
在看一下匹配函数
验证:
输入:
args[0]: abaabcac
args[a]: asdfaddsdabaabcacsdws
输出: 9
先看一下该算法执行的移动过程(即模式串的next数组的值)
先声说明:本人认为该算法在移动值的求法比Horspool不好理解,对于初次接触的人理解会有点难度,不过给予点耐心,还是可以看得懂的
另外下面的 i ,j 变量在下面的函数shiftTable中,请结合理解
未改进:
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
模式串 | a | b | a | a | b | c | a | c |
next | -1 | 0 | 0 | 1 | 1 | 2 | 0 | 1 |
其实next的求法就是:1)如果匹配跳动变量j在下表为0时,遍历变量i和匹配跳动变量j都+1,且next[i] = j;
2)匹配跳动变量j 和遍历变量 i 变量所对应字符一样,便利变量i和匹配跳动变量j都+1,且next[i] = j;
3)以上两种情况不满足,则j = next[j],继续和遍历变量i比较
改进:
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
模式串 | a | b | a | a | b | c | a | c |
next | -1 | 0 | -1 | 1 | 0 | 2 | -1 | 1 |
归纳:其实改进后的算法和为改进相差不是很多,不过时间效率就提高了,就是在第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]; else next[i] = j; } else j = 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; else return -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
相关文章推荐
- KMP字符串匹配算法
- 算法-KMP字符串匹配算法
- MySTL:KMP单模快速字符串匹配算法
- 使用C# 优化KMP字符串匹配算法
- 字符串匹配算法 之 KMP(Knuth-Morris-Pratt)
- KMP字符串匹配算法
- KMP字符串匹配算法
- Python字符串匹配算法KMP实例
- KMP字符串匹配算法
- 数据结构:KMP字符串匹配算法
- 基于有限状态自动机分析KMP字符串匹配算法
- 字符串匹配算法KMP
- 速写KMP字符串匹配算法
- KMP字符串匹配算法
- KMP字符串匹配算法
- KMP字符串匹配算法
- 【小算法】KMP字符串匹配算法实现
- [置顶] 字符串匹配算法KMP详细解释——深入理解
- 字符串匹配算法KMP Java实现
- KMP字符串匹配算法