编程语言
首页 > 编程语言> > KMP算法

KMP算法

作者:互联网

1.KMP算法解决的问题:两个字符串str1,str2,判断str2是否为str1的字串

* 注:abc是abcde的字串,但abd不是

 

2.KMP算法过程

(1).先求字符串前缀和后缀都相等的最大长度(该长度一定小于字符串本身的长度)
* 例:一个字符串abbab,则其前后缀分别为:
* 长度:1 2 3 4 5——等于字符串长度,前后缀对任何字符串都相等,无意义,不考虑
* 前缀:a ab abb abba
* 后缀:b ab bab bbab
* 所以得到最大的前后缀相等长度为2
*
(2).求得一个与字符串对应数组,该数组表示与数组同一位置得字符串的前缀的最大前后缀相等长度(即1过程的值)
* 例:字符串abbab,求得一个对应数组next,则:
* next[0] = -1(字符串0位置前没有字符串), next[1] = 0(前缀字符串a的最大前后缀相等长度为0)
* next[2] = 0(求字符串ab) next[3] = 0(求字符串abb) next[4] = 1(求字符串abba)
*
* 快速求得next[]数组的方法(根据next[i - 1]的值来算next[i]的值)
* 设next[i - 1]的值为a1,则比较str[a1 + 1]与str[i - 1]是否相等,如果相等则next[i] = next[i - 1] + 1
* 如果不相等,则获取next[next[i - 1]]的值a2,比较str[a2 + 1]与str[i - 1]是否相等,如果相等,则:
* next[i] = next[next[i - 1]] + 1; 以此类推,直到得到的a(n)如果为-1,则next[i] = 0
*
(3).比较过程的实现:
* 先通过2过程得到str2的数组next,然后str1和str2开始遍历比较,当找到i位置第一个str1的一部分只部分相等于str2时
* 找到这个相等的str2字串str3,然后得到str3的最大前后缀相等的长度,就将这个后缀代替之前的前缀跟str1从产生不同
* 的位置开始继续往下比较即可
*
* 本质就是当str1与str2比较时,比较到一半发现只是部分相等时,充分利用了部分相等的特点,两者都从一个可行的特定
* 位置开始进行比较

 

代码及解析:

 1 public static int getIndexOf(String s,String m) {
 2         if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
 3             return -1;
 4         }
 5         char[] str1 = s.toCharArray();
 6         char[] str2 = m.toCharArray();
 7         int i1 = 0;
 8         int i2 = 0;
 9         int[] next = getNextArray(str2);
10         while (i1 < str1.length && i2 < str2.length) {
11             if (str1[i1] == str2[i2]) {
12                 i1++;
13                 i2++;
14             } else if (next[i2] == -1) {//当i2已经无法往前跳时,则只能i1往后,i2
15                 i1++;
16             } else {//根据前后缀相等,将它从前缀开始比转为从后缀开始比
17                 i2 = next[i2];
18             }
19         }
20         return i2 == str2.length ? i1 - i2 : -1;
21     }
22     
23     public static int[] getNextArray(char[] ms) {
24         if (ms.length == 1) {
25             return new int[] {-1};
26         }
27         int[] next = new int[ms.length];
28         next[0] = -1;
29         next[1] = 0;
30         int i = 2;
31         int cn = 0;//用来动态变化要处理的位置
32         while (i < next.length) {
33             if (ms[i - 1] == ms[cn]) {
34                 next[i++] = ++cn;
35             } else if (cn > 0) {
36                 cn = next[cn];
37             } else {
38                 next[i++] = 0;
39             }
40         }
41         return next;

 

标签:int,str2,i2,next,后缀,算法,KMP,字符串
来源: https://www.cnblogs.com/jue1e0/p/16210736.html