字符串匹配之KMP《算法很美》

字符串匹配之KMP

思路: 其实就是暴力匹配的改版嘛!要想理解这道题就必须一步一步的去试。

先理解next
next其实就是找前后缀数量
比如:

  • 模串 :b, a, b, b, a, b, b
  • 下标 :0, 1, 2, 3, 4, 5, 6
  • next :0, 0, 1, 2, 3, …

_ _ _ _ _ b "b"的前缀和后缀都为空集,共有元素的长度为0。
_ _ _ _ b a "ba"的前缀为"b",后缀为"a",共有元素的长度为0。
_ _ _ b a b "bab"的前缀为"ba",后缀为"ab",共有元素的长度为1。都有个a。
_ _ b a b a "baba"的前缀为"bab",后缀为"aba",共有元素的长度为2。
_ b a b a b "babab"的前缀为"baba",后缀为"abab",共有元素的长度为3。
b a b a b b 省略。。

发现一个问题没有,如何

具体思路:

  1. int pLength = ps.length(); 获取ps的长度。
  2. int[] next = new int[pLength];开辟根据ps长度的next空间
  3. char[] p = ps.toCharArray(); 将字符串p转成字符数组
  4. next[0] = -1;将第一个next设置好
  5. if (ps.length() == 1) 判断是否长为1,如果只有1就直接返回 return next;
  6. next[1] = 0; 设置第二个next的值
  7. next[] = {-1, 0 , } p[] = {b, a, b, b, a, b, b} 设一个长的
  8. int j = 1; int k = next[j]; k = 0;
  9. 判断 if (k < 0 || p[j] == p[k]) 此时k!<0,p[1] (a) == p[0] (b) 不相等
  10. k = next[0]; 此时 k = -1;
  11. 再判断 此时 k<0 , next[++j] = ++k; next[] = {-1, 0 , 0}
public class KMP {
     
    public static void main(String[] args){
     
        String src = "babababcbabababb";
        int index = indexOf(src, "bababb");
        index = indexOf(src, "bab");
        System.out.println(index);
    }

    private static int indexOf(String s, String p) {
     
        if (s.length() == 0 || p.length() == 0) return -1;
        if (p.length() > s.length()) return -1;

        int count = 0;
        int[] next = next(p);
        int i = 0;//s位置
        int j = 0;//p位置
        int sLen = s.length();
        int pLen = p.length();

        while (i < sLen) {
     
            //①如果 j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
            //j=-1,因为next[0]=-1,说明p的第一位和i这个位置无法匹配,这时i,j都增加1,i移位,j从0开始
            if (j  == -1 || s.charAt(i) == p.charAt(j)) {
     
                i++;
                j++;
            } else {
     
                //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
                //next[j]即为j所对应的next值
                j = next[j];
            }
            if (j == pLen) {
      //匹配成功了
                count++;
                i--;
                j=next[j-1];
//                return (i - j);
            }
        }
        return count;
    }

    private static int[] next(String ps) {
     
        int pLength = ps.length();
        int[] next = new int[pLength];
        char[] p = ps.toCharArray();
        next[0] = -1;
        if (ps.length() == 1)
            return next;
        next[1] = 0;

        int j = 1;
        int k = next[j]; //看看位置j的最长匹配的前缀在哪里

        while (j < pLength - 1) {
     
            //现在要推出next[j+1],检查j和k位置上的关系即可
            if (k < 0 || p[j] == p[k]) {
     
                next[++j] = ++k;
            } else {
     
                k = next[k];
            }
        }
        return next;
    }
}

你可能感兴趣的:(算法很美,算法,字符串)