Java字符串匹配算法

2023-05-16

定义

串(string)是由零个或多个字符组成的有限序列又名叫字符串。

  • 一般地,由n个字符串构成的串记作: S=“a0a1…an-1”(n≥0),其中a_i(1≤i≤n)
  • n是个有限的数值
  • 串一般记为S是串的名称,用引号括起来的字符序列是串的值
  • 可以是字母,数字或其他字符,i就是该字符在串中的位置,串中的字符数目n称为串的长度

子串

在对字符串S做处理时,经常需要取出其中某一连续的片段,称为S的子串(substring)

  • 具体地,由串S中起始于位置i的连续k个字符组成的子串记作substr(S,i,k) = “aiai+1…ai+k-1”,0≤i (n,0≤k)
  • 前缀 prefix(S,k) = substr(S,0,k);
  • 后缀 suffix(S,k) = substr(S,n-k,k)
  • 空格串:只包含空格的串。

BF字符串暴力解法

基本思想

  1. 从主串的第一个字符起与子串的第一个字符进行比较,若相等,则继续对字符串进行后续的比较
  2. 若不相等,则从主串第二个字符起与子串的第一个字符重新比较,以此类推,直到子串中每个字符依次和主串中的一个连续的字符序列相等为止,此时称为匹配成功。
  3. 如果不能在主串中找到与子串相同的字符序列,则匹配失败。

需要进行回溯操作,否则会错过相等的部分

 /**
     *
     * @param parent 主串
     * @param sub 子串
     */
    public static void bruteForce(String parent,String sub){
        //成功匹配的位置
        int index = -1;
        //主串的长度
        int pLen = parent.length();
        //子串的长度
        int sLen = sub.length();

        if (pLen<sLen){
            System.out.println("Error.The main string is greater than the sub string length.");
            return;
        }

        int i = 0;
        int j = 0;
        while (i<pLen&&j<sLen){
            // 判断对应位置的字符是否相等
            if (parent.charAt(i)==sub.charAt(j)){
               //若相等.主串子串继续比较
               i++;
               j++;
            }else{
                //主串回溯到上一次开始匹配的下一个字符
                i = i- j+1;
                j = 0;
            }
        }
        //匹配成功
        if (j >= sLen) {
            index = i - j;
            System.out.println("Successful match,index is:" + index);
        } else {// 匹配失败
            System.out.println("Match failed.");
        }
    }

KMP算法

其核心思想是主串不回溯,模式串尽量多向右移动

首先构造next表(next表里存放的是字符串真后缀与真前缀相同的子字符串最大长度):

以ABCDABD为例说明构建next表

P = ABCDABD
j = 0, prefix(P, 0) = φ
next[0] = -1;//规定如此

P = ABCDABD
j = 1, prefix(P, 1) = A
真前缀: φ
真后缀: φ
next[1] = 0;

P = ABCDABD
j = 2, prefix(P, 2) = AB
真前缀: A
真后缀: B
next[2] = 0;

P = ABCDABD
j = 3, prefix(P, 3) = ABC
真前缀: A,AB
真后缀: BC,C
next[3] = 0;

P = ABCDABD
j = 4, prefix(P, 4) = ABCD
真前缀: A,AB,ABC
真后缀: BCD,CD,D
next[4] = 0;

P = ABCDABD
j = 5, prefix(P, 5) = ABCDA
真前缀: A,AB,ABC,ABCD
真后缀: BCDA,CDA,DA,A
next[5] = 1;

P = ABCDABD
j = 6, prefix(P, 6) = ABCDAB
真前缀: A,AB,ABC,ABCD,ABCDA
真后缀: BCDAB,CDAB,DAB,AB,B
next[6] = 2;

得出next表为:
[-1, 0, 0, 0, 0, 1, 2]

代码实现

package string;

public class KMP {
    //构建next表
    public static int[] buildNext(String sub){
        //构建next表就是查找真前缀 == 真后缀的最大长度,以获取模式串尽量多地往右移动
        int[] next = new int[sub.length()];
        //主串位置
        int j = 0;
        //子串位置
        int t = next[0] = -1;

        while (j<sub.length()-1){
            if (t<0||sub.charAt(j)==sub.charAt(t)){
                j++;
                t++;
                next[j] = t;
            }else {
                t = next[t];
            }
        }
        return next;
    }

    public static void kmp(String parent,String sub){
        int[] next = buildNext(sub);
        //成功匹配的位置
        int index = -1;
        //主串的长度
        int pLen = parent.length();
        //子串的长度
        int sLen = sub.length();

        if (pLen<sLen){
            System.out.println("Error.The main string is greater than the sub string length.");
            return;
        }

        int i = 0;
        int j = 0;
        while (i<pLen&&j<sLen){
            // 判断对应位置的字符是否相等
            if (j==-1||parent.charAt(i)==sub.charAt(j)){
                //若相等.主串子串继续比较
                i++;
                j++;
            }else{
                //i不变,j=next[j]
                j = next[j];
            }
        }
        //匹配成功
        if (j >= sLen) {
            index = i - j;
            System.out.println("Successful match,index is:" + index);
        } else {// 匹配失败
            System.out.println("Match failed.");
        }
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java字符串匹配算法 的相关文章

随机推荐

  • 2021-10-13 关于参数校验及@Valid和@RequestBody注解的组合使用

    一 前言 xff1a 学会并熟悉注解的使用 xff0c 在开发过程中 xff0c 是可以提高效率和简化工作复杂程度的 xff0c 也是会逐渐称为主要编码方式之一 二 1 64 RequestBody注解 xff1a 该注解在处理控制层的请求
  • vue之VueCli4的安装及使用

    一 前言 Vue CLI 是一个基于 Vue js 进行快速开发的完整系统 xff0c 提供 xff1a 通过 64 vue cli 实现的交互式的项目脚手架 通过 64 vue cli 43 64 vue cli service glob
  • 浅谈Mysql数据库

    一 为什么要使用数据库 xff1f 使用一个东西 xff0c 就要清楚它的功能价值 xff0c 才能更好的利用它 xff0c 使我们在工作生活中游刃有余 关于数据库的使用 xff0c 好多人会说 xff0c 一个数据库就是好多张表 xff0
  • java自定义一个数组类(封装多种方法)

    一 自定义数组类的动机 java给定的数组为静态的 xff0c 我们是无法对齐进行灵活的操作 xff0c 比如指定位置添加元素 xff0c 删除元素 xff0c 判断是否非空等 xff0c 于是我们便需要利用 面向对象 的设计模式 xff0
  • 关于JVM(基本常识)

    目录 一 JVM是什么 1 概述 二 为什么要用JVM 1 java程序的执行流程 2 JVM的架构 一 JVM是什么 1 概述 关于JVM xff0c 在百度上的解释为 xff1a JVM是Java Virtual Machine xff
  • JVM之几种常见的JIT优化

    目录 一 公共子表达式消除 xff08 经典的JIT优化技术 xff09 二 方法内联 三 逃逸分析 四 三种逃逸分析优化方式 1 对象的栈上内存分配 2 标量替换 3 同步锁消除 一 公共子表达式消除 xff08 经典的JIT优化技术 x
  • 示例数据库Sakila-db安装(Linux版)

    目录 一 关于Sakila示例数据库 二 安装步骤 三 主要相关命令 一 关于Sakila示例数据库 sakila数据库是国内外对于MySQL研究时广泛使用的一个示例数据库 xff0c 包含了较为大量的数据和使用了合理的数据库结构设计 xf
  • 关于Mysql版本升级迁移数据库时报Error Code: 3554 - Access to system table ‘mysql.innodb_index_stats‘ is rejected错误

    目录 一 背景 二 经过 三 解决 四 总结 一 背景 今天在学习Redis时 xff0c 想到这么一个应用场景 xff1a 如果我们将经常查询的数据先存到Redis中 xff0c 然后每当我们要从数据库查询数据时 xff0c 先查询Red
  • Java自定义实现单链表

    目录 一 自定义java单链表原理概述 二 自定义java单链表功能实现细节 三 实现代码 一 自定义java单链表原理概述 1 单链表概念 单链表是一种链式存取的数据结构 xff0c 用一组地址任意的存储单元存放线性表中的数据元素 链表中
  • 树莓派上使用VSCode配置pyqt环境

    树莓派上在VSCode配置pyqt环境 第一次写博客 xff0c 这两天在树莓派上通过pyqt开发嵌入式软件 xff0c 本人一开始想用在windows上常用的pycharm配置pyqt xff0c 但是发现pycharm安装需要的java
  • postgres 错误duplicate key value violates unique constraint 解决方案

    SELECT setval 39 tablename id seq 39 SELECT MAX id FROM tablename 43 1 主要是 xff1a serial key其实是由sequence实现的 xff0c 当你手动给se
  • React 的生命周期

    挂载 当组件实例被创建并插入 DOM 中时 xff0c 其生命周期调用顺序如下 xff1a constructor 在 React 组件挂载之前 xff0c 会调用它的构造函数 getDerivedStateFromProps 在调用 re
  • Python去掉txt重复行

    coding utf 8 34 34 34 作者 xff1a sunli 日期 xff1a 2022年01月05日 34 34 34 coding utf 8 readDir 61 34 D1 txt 34 writeDir 61 34 D
  • 软件开发的四种模型

    1 gt 瀑布模型 xff1a xff08 1 瀑布模型的特点 xff1a 是线性模型的一种 xff0c 每一个阶段只执行一次 xff1b 这种模型是靠文档驱动的 xff08 2 瀑布模型的优缺点 优点 xff1a 开发的各个阶段比较清晰
  • IDEA 设置 背景 图片 详细步骤(结尾附高清背景图片)

    先上效果图 xff0c 原图在结尾 第一步 xff0c 找到搜索界面 xff0c 在搜索界面搜索 Set Background Image 之后 xff0c 找到想设置的图片的存储路径 接下来设置不透明度Opacity xff0c 越向右
  • Ubuntu 18.04下创建新用户/目录、修改用户权限及删除用户的方法

    Ubuntu 18 04下创建新用户 目录 修改用户权限及删除用户的方法 以下介绍在Ubuntu 18 04系统下创建新用户 目录 修改用户权限及删除用户的正确方法 在Ubuntu系统上创建新用户使用 sudo useradd 用户名 命令
  • 栈和队列练习题

    1 20分 回文序列是指正读反读均相同的字符序列 xff0c 如 abba 和 abdba 均是回文 xff0c 但 good 不是回文 试写一个算法判定给定的字符串是否为回文序列 span class token keyword int
  • mysql数据库忘记密码了怎么办

    本人用的mysql8版本 看到网上很多教程 xff0c 什么修改配置文件my ini 在8版本根本没用 以下是8版本解决办法 亲测可用 1 用管理员身份打开命令行工具 xff08 强调 xff1a 管理员身份 xff09 2 停止mysql
  • Java字符串匹配算法

    定义 串 string 是由零个或多个字符组成的有限序列又名叫字符串 一般地 xff0c 由n个字符串构成的串记作 S 61 a0a1 an 1 n 0 其中a i xff08 1 i n xff09 n是个有限的数值串一般记为S是串的名称
  • win10 vmvare打开虚拟机蓝屏重启,禁用device/credential guard 解决方法

    目录 解决方法在此 win10系统安装的vmware15一打开虚拟机就蓝屏重启 家人们我改了大半天 xff0c 试了友友们各种方法 xff0c 终于发现 xff0c 全都不好使 xff01 11 xff01 xff01 xff01 xff0