KMP算法
作者:互联网
* 注: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