KMP算法开荒

news2024/11/16 18:45:13

文章目录

  • 一 、前言
  • 二、 暴力解法
  • 三、KMP算法原理
    • 3.1 自动子串的指针
    • 3.2 跳过多少个字符
    • 3.3 next数组 - 暴力
    • 3.4 next数组 - 求解
  • 四 KMP实现

一 、前言

字符串匹配

import re
print(re.search('www', 'www.runoob.com').span())  # 在起始位置匹配
print(re.search('com', 'www.runoob.com').span())  # 不在起始位置匹配

SQL中的匹配

SELECT * FROM Persons
WHERE City LIKE '%lon%'

我们注意到这些都是需要用到字符串匹配的,我们再深入想一下,这些字符串是怎么匹配的呢?

二、 暴力解法

public class baoli {

    public static void main(String[] args) {
        String text = "ABABDABACDABABCABAB";//19
        String pattern = "ABABCABAB";//9

        int index = bruteForceMatch(text, pattern);
        if (index == -1) {
            System.out.println("Pattern not found in the text");
        } else {
            System.out.println("Pattern found at index " + index);
        }
    }

    public static int bruteForceMatch(String text, String pattern){
        int n = text.length();
        int m = pattern.length();

        for (int i = 0; i <= n - m; i++) {
            int j;
            for (j = 0; j < m; j++) {
                if (text.charAt(i + j) != pattern.charAt(j)) {
                    break;
                }
            }

            if (j == m) {
                return i; // 匹配成功,返回起始位置
            }
        }

        return -1; // 匹配失败
    }
}

看到这种brute force暴力解法的时间复杂度为O(mn)

一个字一个字的匹配,一旦出错就匹配下一个

在这里插入图片描述
但是这样带来了巨大的浪费

三、KMP算法原理

在这里插入图片描述

KMP算法是用的这三位大佬的名字首字母,没有什么特殊含义

3.1 自动子串的指针

在这里插入图片描述
匹配失败,已经知道了前面读过了哪些char,所以移动子串的指针

在这里插入图片描述

3.2 跳过多少个字符

在这里插入图片描述

KMP算法会定义一个next数组,记录对应 可以跳过字符的个数

    public static int kmpSearch(String text, String pattern) {
        int[] next = computeLPSArray(pattern);

        int i = 0; // text的指针
        int j = 0; // pattern的指针

        while (i < text.length()) {
            if (text.charAt(i) == pattern.charAt(j)) { // char匹配,都后移
                i++;
                j++;

                if (j == pattern.length()) {
                    return i - j; // string匹配成功,返回起始位置
                }
            } else {
                if (j != 0) { // char匹配失败,pattern回退到上一个匹配的位置
                    j = next[j - 1];
                } else { // 字符串第一个就匹配失败,直接后移
                    i++;
                }
            }
        }

        return -1; // 匹配失败
    }

3.3 next数组 - 暴力

在这里插入图片描述

next数组:寻找子串中“相同前后缀的最长长度,不能是字符串本身”

那么如何获取这个next数组呢,当然首先可以想到for循环暴力求解

    public static int[] bruteComputeLPSArray(String pattern) {
        int[] lps = new int[pattern.length()];
        int len = 0;

        for (int i = 1; i <= pattern.length() - 1; i++) {
            if (pattern.charAt(i) == pattern.charAt(len)) {
                len++;
                lps[i] = len;
            } else {
                if (len != 0) {
                    len = lps[len - 1];
                    i--;
                } else {
                    lps[i] = 0;
                }
            }
        }

        return lps;
    }

3.4 next数组 - 求解

在这里插入图片描述

下一步相同,那么直接就是2+1
下一步不同呢?

在这里插入图片描述

左边这部分前后缀 = 右边这部分前后缀

直接在左边进行查找即可

在这里插入图片描述
于是又开始,寻找下一个char是否相同

    public static int[] computeLPSArray(String pattern) {
        int[] next = new int[pattern.length()];
        int len = 0; // 最长公共前后缀的长度
        int i = 1; // pattern的指针

        while (i < pattern.length()) {
            if (pattern.charAt(i) == pattern.charAt(len)) {
                len++;
                next[i] = len;
                i++;
            } else {
                if (len != 0) {
                    len = next[len - 1]; // 回退到前一个匹配的位置
                } else {
                    next[i] = 0;
                    i++;
                }
            }
        }

        return next;
    }

四 KMP实现

package com.KMP;


public class KMPAlgorithm {
    public static void main(String[] args) {
        String text = "ABABDABACDABABCABAB";
        String pattern = "ABABCABAB";

        int index = kmpSearch(text, pattern);
        if (index == -1) {
            System.out.println("Pattern not found in the text");
        } else {
            System.out.println("Pattern found at index " + index);
        }
    }

    public static int kmpSearch(String text, String pattern) {
        int[] next = computeLPSArray(pattern);

        int i = 0; // text的指针
        int j = 0; // pattern的指针

        while (i < text.length()) {
            if (text.charAt(i) == pattern.charAt(j)) { // char匹配,都后移
                i++;
                j++;

                if (j == pattern.length()) {
                    return i - j; // string匹配成功,返回起始位置
                }
            } else {
                if (j != 0) { // char匹配失败,pattern回退到上一个匹配的位置
                    j = next[j - 1];
                } else { // (j == 0) 字符串第一个就匹配失败,直接后移
                    i++;
                }
            }
        }

        return -1; // 匹配失败
    }

    public static int[] computeLPSArray(String pattern) {
        int[] next = new int[pattern.length()];
        int len = 0; // 最长公共前后缀的长度
        int i = 1; // pattern的指针

        while (i < pattern.length()) {
            if (pattern.charAt(i) == pattern.charAt(len)) {
                len++;
                next[i] = len;
                i++;
            } else {
                if (len != 0) {
                    len = next[len - 1]; // 回退到前一个匹配的位置
                } else {
                    next[i] = 0;
                    i++;
                }
            }
        }

        return next;
    }

    public static int[] bruteComputeLPSArray(String pattern) {
        int[] lps = new int[pattern.length()];
        int len = 0;

        for (int i = 1; i <= pattern.length() - 1; i++) {
            if (pattern.charAt(i) == pattern.charAt(len)) {
                len++;
                lps[i] = len;
            } else {
                if (len != 0) {
                    len = lps[len - 1];
                    i--;
                } else {
                    lps[i] = 0;
                }
            }
        }

        return lps;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/935219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java“牵手”天猫商品sku信息API接口数据,天猫API接口申请指南

天猫平台商品sku属性信息接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取天猫商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品销量接口API是一种用于获取电商平台上商品sku属性数据的接口&#…

无涯教程-KNN算法 - 寻找最近邻居

K最近邻(KNN)算法是一种监督的ML算法&#xff0c;可用于分类以及回归预测问题&#xff0c;但是&#xff0c;它主要用于行业中的分类预测问题。以下两个属性将很好地定义KNN- 惰性学习算法 - KNN是一种惰性学习算法&#xff0c;因为它没有专门的训练阶段&#xff0c;并且在分…

Java-继承和多态(下)

补全构造方法 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);while (scanner.hasNextInt()) {int x scanner.nextInt();int y scanner.nextInt();int z scanner.nextInt();Sub sub new…

【Python】基于Python的电话簿(Phonebook project)设计【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

使用Rust开发命令行工具

生成二进制文件&#xff0c;将其扔到环境变量的path下即可~ 用rust打造实时天气命令行工具[1] 找到合适的API 使用该api[2] 如请求 api.openweathermap.org/data/2.5/weather?qBeijing&appidyour_key: { "coord": { "lon": 116.3972, "lat&quo…

变天了,国产技术突破让黑黄金变成白菜价,芯片技术变革时代来了

由于众所周知的原因&#xff0c;美国企图利用它掌握的硅基芯片技术体系&#xff0c;阻止中国发展先进芯片&#xff0c;不过中国科技界在一项重要芯片材料方面已取得重大突破&#xff0c;还让这种芯片材料变成白菜价&#xff0c;将改变硅基芯片技术主导的时代。 这种芯片材料就是…

小研究 - JVM 的类装载机制

本文通过对一个类装载实例的分析&#xff0c;阐明了 Java虚拟机的类装载的代理机制和由此定义的命名空间&#xff0c;指出了类装载机制在容器/组件/抽象框架结构中的作用。 目录 1 引言 2 实例 3 分析 3.1 类装载的代理机制 3.2 Java的命名空间 3.3 解决问题 4 应…

全栈之前端 | 1.CSS3必备基础知识学习

关注回复【学习交流群】加入【安全开发运维】答疑交流群 请朋友们【多多点击文中的广告】&#xff0c;支持作者更新更多文章。 目录: 0x00 前言简述 描述: 前面跟随着WeiyiGeeker作者【全栈工程师修炼指南】公众号一起学习了前端基础的知识以及HTML标签、属性、事件、字符集系列…

寻找注册配置中心最佳评测官,赢取丰厚奖品 | 测评开启,开发者请速速集结

评测前请点击文末链接&#xff0c;领取 MSE-Nacos 免费试用&#xff0c;再启动评测。 注册配置中心 MSE-Nacos (以下简称 MSE-Nacos)&#xff0c;即 Nacos 的企业版&#xff0c;开箱即用的 Nacos 云服务&#xff0c;对 Nacos 内核进行企业级稳定性加固&#xff0c;故障自动检测…

统计学补充概念-13-逻辑回归

概念 逻辑回归&#xff08;Logistic Regression&#xff09;实际上是一种用于解决分类问题的统计学习方法&#xff0c;尽管其名称中带有"回归"一词&#xff0c;但它主要用于处理分类任务。逻辑回归用于预测一个事件发生的概率&#xff0c;并将其映射到一个特定的输出…

js的this指向问题

代码一&#xff1a; 这段代码定义了run函数、obj对象&#xff0c;然后我们把run函数作为obj的方法。 function run(){console.log(this);}let obj{a:1,b:2};obj.runrun;obj.run(); 那么我们调用obj的run方法&#xff0c;那么这个方法打印的this指向obj。 分析&#xff1a;即…

第十三课 宾语从句

文章目录 前言一、宾语从句1、主语及物动词宾语从句2、主语双宾动词间接宾语直接宾语3、主语特定及物动词宾语从句&#xff08;作宾语&#xff09;宾补4、主语be某些形容词宾语从句5、动词不定式后面的宾语从句6、动名词后面的宾语从句7、介词后面的宾语从句9、间接引语 前言 一…

基于LOF算法的异常值检测

目录 LOF算法简介Sklearn官网LOF算法应用实例1Sklearn官网LOF算法应用实例2基于LOF算法鸢尾花数据集异常值检测读取数据构造数据可视化&#xff0c;画出可疑异常点LOF算法 LOF算法简介 LOF异常检测算法是一种基于密度的异常检测算法&#xff0c;基于密度的异常检测算法主要思想…

Centos7安装ZK-UI管理界面安装|Maven|Git|

一: JDK1.8安装 参考: Centos7卸载|安装JDK1.8|Xshell7批量控制多个终端 二&#xff1a;Maven安装 2.1&#xff1a;下载maven安装包 maven 下载地址&#xff1a;https://mirror.bit.edu.cn/apache/maven/maven-3/ [rootwww ~]# mkdir -p /usr/local/maven [rootwww ~]# …

【C/C++】多态的概念 | 虚函数 | 虚函数指针

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

Linux操作系统--vi/vim编辑器

1.Vi/Vim简介 Vi 是 Unix 操作系统和类 Unix 操作系统中最通用的文本编辑器。 VIM 编辑器是从 VI 发展出来的一个性能更强大的文本编辑器。可以主动的以字体颜色辨别语法的正确性,方便程序设计。VIM 与 VI 编辑器完全兼容。这里简单的理解为如果你需要使用指令取操作Linux系…

【LeetCode-中等题】142. 环形链表 II

文章目录 题目方法一&#xff1a;哈希表set去重方法二&#xff1a;快慢指针 题目 方法一&#xff1a;哈希表set去重 思路&#xff1a;我们遍历链表中的每个节点&#xff0c;并将它记录下来&#xff1b;一旦遇到了此前遍历过的节点&#xff0c;就可以判定链表中存在环。借助哈希…

nonlocal关键字声明

nonlocal关键字声明 作用 使得内层函数可以使用/修改外层函数的变量 值得注意的是&#xff0c;在未使用nonlocal声明时 对于外层函数中的可变对象&#xff0c;内层函数即可访问&#xff0c;也可以修改 def outer():x, y [1], [2]def inner(z):x.append(1)print(x)print(z)r…

英特尔oneAPI人工智能黑客松 - 坚果识别实战

写在前面&#xff1a;博主是一只经过实战开发历练后投身培训事业的“小山猪”&#xff0c;昵称取自动画片《狮子王》中的“彭彭”&#xff0c;总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域&#xff0c;如今终有小成…

Ubuntu断电重启后黑屏左上角光标闪烁,分辨率低解决办法,ubuntu系统display只有4:3 怎么办?太卡

这个问题主要是显卡驱动问题&#xff0c;按照步骤更新显卡驱动 1&#xff0c;选择metapackage 并且选择proprietary版本&#xff0c;选择版本号选择最新的版本。 2&#xff0c;具体步骤参考 前言 笔者在安装显卡驱动时并未遇到问题&#xff0c;主要是后续屏幕亮度无法调节&…