关键词查找【Knuth-Morris-Pratt (KMP) 算法】

一个视频让你彻底学懂KMP算法_哔哩哔哩_bilibili

KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。

第一步:计算模式串(子串)和nextj数组

模式串 前2位字母的nextj固定是0 和 1

后续字母的nexj,aba 里的第三位的nextj =首尾相同子字符串长度+1,ab首尾相同子字符串长度为0

后续字母的nexj,abaa 里的第四位的nextj =首尾相同子字符串长度+1,aba首尾相同子字符串(a)长度为1

后续字母的nexj,abaab 里的第五位的nextj =首尾相同子字符串长度+1,abaa首尾相同子字符串(a)长度为1

后续字母的nexj,abaabc 里的第六位的nextj =首尾相同子字符串长度+1,abaaab首尾相同子字符串(ab)长度为2

第六位第七位 以此类推。。。

第二步:主串和子串比对过程中遇到不匹配字母时,用子串里不匹配的字母去数组里找 nextj

下图:c和b不匹配,用b去数组里找到nexj=1,图二j挪到第一位,继续比较

下图:c和a不匹配,用a去数组里找到nexj=0,图二j挪到第0位,然后i和j 都往后移一位继续比较

下图:a和c不匹配,用c去数组里找到nexj=3,图二j挪到第3位,继续比较

实现代码如下:

java 复制代码
public class KMP {
     
    // 计算部分匹配表 (LPS)
    private static int[] computeLPSArray(String pattern) {
        int[] lps = new int[pattern.length()];
        int length = 0; // 长度为当前最长前缀后缀
        int i = 1;
 
        while (i < pattern.length()) {
            if (pattern.charAt(i) == pattern.charAt(length)) {
                length++;
                lps[i] = length;
                i++;
            } else {
                if (length != 0) {
                    length = lps[length - 1]; // 回溯
                } else {
                    lps[i] = 0;
                    i++;
                }
            }
        }
        return lps;
    }
 
    // KMP 查找算法
    public static boolean kmpSearch(String text, String pattern) {
        int[] lps = computeLPSArray(pattern);
        int i = 0; // 文本的索引
        int j = 0; // 模式串的索引
 
        while (i < text.length()) {
            if (pattern.charAt(j) == text.charAt(i)) {
                i++;
                j++;
            }
 
            if (j == pattern.length()) {
                return true; // 找到匹配
            } else if (i < text.length() && pattern.charAt(j) != text.charAt(i)) {
                if (j != 0) {
                    j = lps[j - 1]; // 根据 LPS 表回溯
                } else {
                    i++;
                }
            }
        }
        return false; // 未找到匹配
    }
 
    public static void main(String[] args) {
        String text = "aaaaaaac";
        String pattern = "aaaac";
 
        boolean found = kmpSearch(text, pattern);
        if (found) {
            System.out.println("子串 \"" + pattern + "\" 在主串中出现过。");
        } else {
            System.out.println("子串 \"" + pattern + "\" 在主串中未出现。");
        }
    }
}

相关:

https://blog.csdn.net/qq_43197840/article/details/140680621?spm=1001.2014.3001.5501

https://blog.csdn.net/qq_43197840/article/details/140679425?spm=1001.2014.3001.5501

相关推荐
许彰午4 分钟前
JWT的四种设计策略——轻量负载缓存外置上下文线程统一验证
java·安全·缓存·tomcat
计算机安禾20 分钟前
【算法分析与设计】第46篇:近似难度与不可近似性理论
网络协议·算法·ssl
小bo波39 分钟前
Java Swing 可视化素数筛:动态演示 1~120 质数筛选【附完整源码】
java·算法·可视化·swing·素数
imDwAaY1 小时前
贝叶斯网络到粒子滤波Python算法实现 CS188 Proj4 学习笔记
网络·人工智能·笔记·python·学习·算法
sleven fung1 小时前
Whisper库
开发语言·人工智能·python·算法·ai·whisper
Black蜡笔小新1 小时前
自动化AI算法训练服务器DLTM零代码私有化一站式AI训练平台技术解析
人工智能·算法·自动化
天若有情6731 小时前
【C++趣味实战】仿写Burp代理逻辑!自定义可控迭代器:拦截Intercept/放行Forward/重放Repeater全实现
java·开发语言·c++
迷藏4941 小时前
Python+DuckDB:轻量级BI流水线实战
java·开发语言·python·原型模式
磊 子1 小时前
C++function与bind绑定器讲解
java·jvm·c++
咋吃都不胖lyh1 小时前
短期记忆和长期记忆都存 MySQL
android·java·开发语言