代码随想录训练营day09: KMP算法, strStr()的实现

这次的KMP算法还是很有难度的, 我搞懂了next数组的创建, 但是没有搞懂是如何匹配的, 所以今天就先了解下, 之后再回头来看

关键点就是: 找到最长相等前后缀

构造next数组三步:

初始化: 定义两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置(next数组下标)

前后缀不相等的情况: 不相等的话就向前回退 j = next[j - 1]

前后缀相等的情况: 如果相等了就j++

class Solution {
    public void getNext(int[] next, String s){
        int j = 0;
        next[0] = j;
       //遍历数组来对ij匹配, 这里的i是j后面一个
        for (int i = 1; i<s.length(); i++){
            //判断不相等的情况
            while(j>=0 && s.charAt(i) != s.charAt(j)){
                j=next[j - 1];
            }
            //相等的话就j++
            if(s.charAt(i)==s.charAt(j)){
                j++;
            }
            next[i] = j;
        }
    }

下面的匹配部分没有很理解, 直接上代码算了

(注意:这里的i和j有点不同)

public int strStr(String haystack, String needle) {
        if(needle.length()==0){
            return 0;
        }

        int[] next = new int[needle.length()];
        getNext(next, needle);
        int j = -1;
        for(int i = 0; i<haystack.length();i++){
            while(j>=0 && haystack.charAt(i) != needle.charAt(j+1)){
                j = next[j];
            }
            if(haystack.charAt(i)==needle.charAt(j+1)){
                j++;
            }
            if(j==needle.length()-1){
                return (i-needle.length()+1);
            }
        }

        return -1;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法和BM算法是两种常用的字符串匹配算法。 KMP算法的思想是,当出现不匹配时,已经匹配过的前缀中一定有一部分是可以直接跳过的,不需要重新匹配。通过预处理模式串,得到一个next数组,用于记录模式串中每个前缀的最长可匹配前缀长度。在匹配时,当文本串中出现不匹配字符时,根据next数组可以直接跳过一部分已经匹配过的前缀,从而提高匹配效率。 KMP算法的JAVA代码实现如下: ```java public class KMP { public static int kmp(String text, String pattern) { int[] next = getNext(pattern); int i = 0, j = 0; while (i < text.length() && j < pattern.length()) { if (j == -1 || text.charAt(i) == pattern.charAt(j)) { i++; j++; } else { j = next[j]; } } if (j == pattern.length()) { return i - j; } else { return -1; } } private static int[] getNext(String pattern) { int[] next = new int[pattern.length()]; next[0] = -1; int i = 0, j = -1; while (i < pattern.length() - 1) { if (j == -1 || pattern.charAt(i) == pattern.charAt(j)) { i++; j++; next[i] = j; } else { j = next[j]; } } return next; } } ``` BM算法的思想是,在匹配过程中尽可能地多跳过一些字符,从而提高匹配效率。它的核心是两个规则:坏字符规则和好后缀规则。坏字符规则用于处理文本串和模式串不匹配的情况,好后缀规则用于处理文本串和模式串匹配的情况。 BM算法的JAVA代码实现如下: ```java public class BM { public static int bm(String text, String pattern) { int[] bc = generateBC(pattern); int[] suffix = new int[pattern.length()]; boolean[] prefix = new boolean[pattern.length()]; generateGS(pattern, suffix, prefix); int i = 0, j = 0; while (i <= text.length() - pattern.length() + j) { for (j = pattern.length() - 1; j >= 0; j--) { if (text.charAt(i + j) != pattern.charAt(j)) { break; } } if (j < 0) { return i; } int x = j - bc[(int) text.charAt(i + j)]; int y = 0; if (j < pattern.length() - 1) { y = moveByGS(j, pattern.length(), suffix, prefix); } i = i + Math.max(x, y); } return -1; } private static int[] generateBC(String pattern) { int[] bc = new int[256]; for (int i = 0; i < 256; i++) { bc[i] = -1; } for (int i = 0; i < pattern.length(); i++) { int ascii = (int) pattern.charAt(i); bc[ascii] = i; } return bc; } private static void generateGS(String pattern, int[] suffix, boolean[] prefix) { int len = pattern.length(); for (int i = 0; i < len; i++) { suffix[i] = -1; prefix[i] = false; } for (int i = 0; i < len - 1; i++) { int j = i; int k = 0; while (j >= 0 && pattern.charAt(j) == pattern.charAt(len - 1 - k)) { j--; k++; suffix[k] = j + 1; } if (j == -1) { prefix[k] = true; } } } private static int moveByGS(int j, int len, int[] suffix, boolean[] prefix) { int k = len - 1 - j; if (suffix[k] != -1) { return j - suffix[k] + 1; } for (int r = j + 2; r <= len - 1; r++) { if (prefix[len - r]) { return r; } } return len; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值