KMP算法

2023-09-22 10:57:37

卡尔老师视频链接

KMP算法:

  • KMP算法,全称为Knuth-Morris-Pratt算法,是一种用于字符串匹配的高效算法。它的主要思想是利用已经匹配过的字符信息,避免不必要的回溯,从而提高匹配的效率。
  • KMP算法的核心是构建一个辅助数组next,用来记录模式串中每个字符对应的最长公共前缀和后缀的长度。通过这个数组,可以在匹配过程中根据已匹配的前缀信息,跳过一些不必要的比较。

具体的匹配过程如下:

  1. 首先,根据模式串构建next数组。next[i]表示模式串中以第i个字符结尾的子串的最长公共前缀和后缀的长度。
  2. 然后,从文本串的第一个字符开始,与模式串的第一个字符进行比较。
  3. 如果当前字符匹配成功,则依次比较下一个字符,直到模式串结束或者字符不匹配。
  4. 如果当前字符匹配失败,则根据next数组的值,移动模式串的位置,继续与文本串中的下一个字符进行比较。
    • 如果next[j] = -1,表示模式串需要移动到下一个位置,即i++;
    • 如果next[j] ≠ -1,表示模式串需要向右移动的位置为j - next[j]。

KMP算法的时间复杂度为O(m +
n),其中m为模式串的长度,n为文本串的长度。相比于朴素的字符串匹配算法,KMP算法通过利用已匹配的前缀信息,避免了一些不必要的比较,从而提高了匹配的效率。

public class Kmp {
    // 构建next数组
    private int[] buildNext(String pattern) {
        int[] next = new int[pattern.length()]; // next数组,用于记录最长公共前缀和后缀的长度
        int i = 0; // pattern的索引
        int j = -1; // next数组的值

        next[0] = -1; // 第一个字符的next值为-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;
    }

    // KMP算法匹配
    public int kmpMatch(String text, String pattern) {
        int[] next = buildNext(pattern);
        System.out.println("next数组:");
        for(int i=0;i<next.length;i++){
            if(i==next.length-1){
                System.out.print(next[i]+"\n");
            }else{
                System.out.print(next[i]);
            }
        }
        int i = 0; // text的索引
        int j = 0; // pattern的索引

        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; // 没有匹配的子串
        }
    }

    // 测试
    public static void main(String[] args) {
        String text = "abbabbababaaababaaababab";//文本串
        String pattern = "ababaaababaa";//模式串
        Kmp kmp=new Kmp();
        int index = kmp.kmpMatch(text, pattern);

        if (index != -1) {
            System.out.println("在位置 " + index + " 处找到匹配的子串");
        } else {
            System.out.println("未找到匹配的子串");
        }
    }
}

在这里插入图片描述

解释一下,KMP算法中的next数组的构建部分:

  1. 首先,创建一个长度为模式串长度的next数组。然后,定义两个指针i和j,分别用于指向模式串中的字符和next数组中的值。
  2. 接下来,将第一个元素的next值设置为-1,表示没有公共前缀和后缀。
  3. 然后,使用while循环遍历模式串中的字符,直到遍历到倒数第二个字符。在循环中,判断j的值是否为-1或者当前字符与对应位置的字符相等。
  4. 如果j的值为-1,表示没有找到公共前缀和后缀,此时将i和j都向后移动一位,并将next[i]的值设置为j。
  5. 如果当前字符与对应位置的字符相等,表示找到了公共前缀和后缀,此时将i和j都向后移动一位,并将next[i]的值设置为j。
  6. 如果j的值不为-1且当前字符与对应位置的字符不相等,表示当前字符与j位置处的字符不匹配,需要将j的值更新为next[j],即回退到之前相同前缀的位置。
  7. 最后,返回构建好的next数组。

简单地说一下next数组吧:
1、先求模式串每个子串的最长公共前后缀
2、然后看题目要求(有时候你得两种情况都抽一眼)
(1)下标从0开始:将上面求的数组整体右移一位(第一位补-1)
(2)下标从1开始:将第一种情况求得的数组加1

更多推荐

蓝桥杯 题库 简单 每日十题 day7

01啤酒和饮料题目描述本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐酒。#include<stdio.h>#include<stdlib.h>intmain()

基于SpringBoot的教师工作量管理系统

目录前言一、技术栈二、系统功能介绍管理员模块的实现教师模块的实现三、核心代码1、登录模块2、文件上传模块3、代码封装前言随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了教师工作量管理系统的开发全过程。通过分析教师工作量管理系统管理的不足,创建了一个计算机管理教师工作量管理系统

深眸科技迭代深度学习算法,以AI机器视觉技术扩围工业应用场景

智能制造是制造业数智化转型升级的发展方向,在当前以高端装备制造为核心的工业4.0时代背景下,越来越多的制造企业意识到机器视觉对于提高效率、降低成本,从而提升企业效益的意义。目前,机器视觉已成为制造业迈向智能制造过程中极其关键的一项技术,且通过融合人工智能,能够实现该技术的再一次升级,以此切入更多差异化工业应用场景,并以

软件设计模式

1.UML1.1类图表示法uml类图中,类使用包含类名、属性、方法属性或方法前的加好和减号表示了这个方法的可见性,可见性的符号有三种:+表示public-表示private#表示protected1.2类与类之间关系关联关系单向关联双向关系自关联聚合关系聚合关系是关联关系的一种,是强关联关系,是整体和部分的关系聚合关系

海艺互娱与亚马逊云科技合作,在生成式AI领域探索更多的训练方向

面对生成式AI(GenerativeAI)新浪潮,如何把握机遇,加速创新发展,智胜蓝海?通过与亚马逊云科技合作,海艺互娱使用云上便捷部署的生成式AI解决方案,快速构建起可以服务全球用户的seaart.ai艺术创作平台,让用户将灵感快速转化为作品的同时,实现成本优化。当前,随着人工智能的快速发展,生成式AI正以其惊人的创

海外媒体发稿:海外汽车媒体推广9个方式解析

根据下列9个国外汽车媒体推广方式,企业能够在国际范围内突破边界,获得领域关心。这将帮助企业完成国际化发展发展战略,扩展市场占有率和提升盈利空间。【华媒舍】国外全媒体发表文章将会成为企业完成这一目标的重要方式,为企业带来新的机遇与挑战,助推企业与时俱进和成长!1.提升国界线,开拓视野!国外汽车媒体是汽车业务领域散播信息的

play() failed because the user didn‘t interact with the document优化媒体不能自动播放

1.问题谷歌浏览器video元素设置autoplay,我们原意是希望页面加载时自动播放,但实际上并没有自动播放,在控制台报错如下:Uncaught(inpromise)DOMException:play()failedbecausetheuserdidn’tinteractwiththedocumentfirst.这里

前端面试题整理

1.沙箱隔离前端沙箱隔离(Frontendsandboxisolation)是一种安全机制,用于将前端代码与主机环境隔离开来,以保护系统的安全性和稳定性。在Web开发中,前端代码通常由JavaScript编写,而JavaScript是一种强大且灵活的语言,但它也可能存在一些安全风险。例如,恶意用户可能会通过前端代码执行

JavaEE初阶(5)多线程案例(定时器、标准库中的定时器、实现定时器、线程池、标准库中的线程池、实现线程池)

接上次博客:JavaEE初阶(4)(线程的状态、线程安全、synchronized、volatile、wait和notify、多线程的代码案例:单例模式——饿汉懒汉、阻塞队列)_di-Dora的博客-CSDN博客目录多线程案例定时器标准库中的定时器实现定时器线程池标准库中的线程池实现线程池多线程案例定时器定时器(Tim

Qt/C++音视频开发53-本地摄像头推流/桌面推流/文件推流/监控推流等

一、前言编写这个推流程序,最开始设计的时候是用视频文件推流,后面陆续增加了监控摄像头推流(其实就是rtsp视频流)、网络电台和视频推流(一般是rtmp或者http开头m3u8结尾的视频流)、本地摄像头推流(本地USB摄像头或者笔记本自带摄像头等)、桌面推流(将当前运行环境的系统桌面抓拍推流)。按照分类的话其实就是三大类

【Robotframework+python】实现http接口自动化测试

前言下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测试框架,以至于后期rd每修改一个bug,经常导致之前没有问题的case又产生了bug,所以需要一遍遍回归case,过程一直手工去执行,苦不堪言。所以,对于即将开始的http接口测试需求,立马花了两天时

热文推荐