java暴力匹配及KMP算法解决字符串匹配问题示例详解

Java暴力匹配及KMP算法解决字符串匹配问题

1. 概述

在字符串匹配问题中,有两种经典的算法:暴力匹配和KMP算法。暴力匹配是最简单的字符串匹配算法,其思路是将字符串的每个子串与目标字符串进行匹配。KMP算法是一种更高效的字符串匹配算法,它通过预处理字符串的next数组来避免不必要的字符比较,从而在匹配过程中提高效率。

2. Java暴力匹配

暴力匹配算法一般用于小规模字符串的匹配问题,其时间复杂度最大可达O(mn),其中m和n分别为目标字符串和匹配串的长度。Java中可以使用String中的indexOf方法来实现暴力匹配。

例如,我们要在目标字符串str中查找子串sub,可以用如下代码实现:

String str = "hello world";
String sub = "world";
int index = str.indexOf(sub);
if (index != -1) {
    System.out.println("匹配成功,子串的起始位置为" + index);
} else {
    System.out.println("匹配失败,子串不存在");
}

输出结果为:

匹配成功,子串的起始位置为6

3. KMP算法

KMP算法的核心思想是,在匹配失败时,尽可能地利用已经匹配成功的信息,不再重头开始匹配。KMP算法通过预处理字符串的next数组,可以在匹配过程中直接跳过不必要的字符比较,从而提高匹配效率。

KMP算法的代码实现分为两个部分,第一部分是预处理字符串的next数组,第二部分是匹配过程。以下是一个KMP算法示例代码,其中target为目标串,pattern为匹配串。

public static int kmp(String target, String pattern) {
    int n = target.length();
    int m = pattern.length();
    int[] next = getNext(pattern); // 预处理next数组
    int i = 0, j = 0; // i为目标串的指针,j为匹配串的指针
    while (i < n && j < m) {
        if (j == -1 || target.charAt(i) == pattern.charAt(j)) { // 匹配成功,或j已经回溯到匹配串的起始位置
            i++;
            j++;
        } else { // 匹配失败,回溯到next[j]处继续匹配
            j = next[j];
        }
    }
    if (j == m) { // 匹配成功,返回匹配位置的起始位置
        return i - j;
    } else { // 匹配失败
        return -1;
    }
}

private static int[] getNext(String str) {
    int[] next = new int[str.length()];
    int j = -1, i = 0;
    next[0] = -1;
    while (i < str.length() - 1) {
        if (j == -1 || str.charAt(i) == str.charAt(j)) { // 匹配成功
            i++;
            j++;
            next[i] = j;
        } else { // 匹配失败
            j = next[j];
        }
    }
    return next;
}

4. 示例演示

以下是一个KMP算法的匹配示例:

假设有两个字符串,目标字符串为target="abababaabacaba",匹配模式串为pattern="aba"。在这个示例中,我们需要在target中寻找是否有与pattern匹配的子串,并返回其起始位置。

首先,我们通过getNext方法预处理pattern的next数组。next[i]表示pattern的前i个元素中,最长相同前缀和后缀的长度。

int[] next = getNext("aba");
// next = [-1, 0, 0]

接着,我们利用next数组进行匹配。在匹配过程中,i指向target的当前位置,j指向pattern的当前位置。如果匹配成功,我们将i和j分别向后移动一位;如果匹配失败,则j回溯到next[j]处继续匹配。当j遍历完整个pattern时,说明匹配成功,我们返回匹配的起始位置。

int index = kmp("abababaabacaba", "aba");
// 匹配成功,返回值为0,即目标串的起始位置

以上就是一个KMP算法的匹配示例。实际上,KMP算法在处理大规模字符串时,具有较高的时间效率,相比于暴力匹配算法,KMP算法的时间复杂度仅为O(m+n)。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java暴力匹配及KMP算法解决字符串匹配问题示例详解 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • java 实现数组扩容与缩容案例

    下面是详细的讲解: 背景 在Java中,数组是一种常见的数据结构,但是它具有固定长度的限制,因此需要进行扩容与缩容的操作。实现数组扩容与缩容可以提高程序的灵活性和效率,因此很有必要进行了解和掌握。 实现方法 Java中的数组扩容与缩容可以通过以下三种方法来实现: 手动操作:通过新建一个更大/更小的数组,并将原有的元素拷贝到新数组中来实现扩容/缩容操作; 利用…

    Java 2023年5月26日
    00
  • Spring Security实现基于RBAC的权限表达式动态访问控制的操作方法

    基于RBAC的权限表达式动态访问控制是Spring Security中常用的一种权限控制方式。以下是具体的实现方法: 1. 定义RBAC模型 可参考以下示例: ### 角色 1. 管理员 2. 普通用户 ### 权限 1. 用户管理:创建、删除用户 2. 文章管理:查看、修改、删除所有文章;创建、修改、删除自己的文章 ### 资源 – 用户: /user/*…

    Java 2023年6月3日
    00
  • python实现数独算法实例

    python实现数独算法实例 介绍 数独是一种流行的逻辑游戏,也是计算机科学中常见的算法和数据结构问题。本文将介绍基于python实现数独算法的完整攻略。 算法原理 数独算法的原理可以归纳为两部分: 约束传播(Constraint Propagation)——基于已知的数推断未知的数; 回溯(Backtracking)——在没有更多的约束传播时,回溯到之前的…

    Java 2023年5月30日
    00
  • java编写简单的ATM存取系统

    下面是Java编写简单的ATM存取系统的完整攻略。 1. 确定需求分析 在开始编写ATM系统之前,我们需要对系统的需求进行分析和确认。该系统的主要功能包括: 可以登录和注册账户 可以查询账户余额 可以取款和存款 可以修改账户密码 可以退出系统 2. 设计系统架构 确定了需求之后,我们需要设计ATM系统的整体架构。整个系统需要有以下几个模块: 用户登录和注册模…

    Java 2023年5月19日
    00
  • Idea2020.2创建JavaWeb项目(部署Tomcat)方法详解

    Idea2020.2创建JavaWeb项目(部署Tomcat)方法详解 在你使用 IntelliJ IDEA(以下简称 IDEA)创建基于 JavaWeb 技术的 Web 项目时,需要在 IDEA 中设置 Tomcat 服务器,并在项目部署时将其与 Tomcat 进行绑定,以便成功启动和访问。接下来就为你详细讲解使用 Idea2020.2 创建 JavaWe…

    Java 2023年6月2日
    00
  • 什么是线程调度?

    以下是关于线程调度的完整使用攻略: 什么是线程调度? 线程调度是指操作系统或者虚拟机在多线程环境下,按照一定的策略配 CPU 时间片给各个线程执行的过程。在多线程编程中,线程调度是非常重要的,它直接影到程序的性能和响应速度。 线程调度的主要任务是: 分配 CPU 时间片给各个线程执行; 确定的优先级; 确定线程的状态,如就绪、运行、阻塞等。 线程调度的实现方…

    Java 2023年5月12日
    00
  • Java基于动态规划法实现求最长公共子序列及最长公共子字符串示例

    Java基于动态规划法实现求最长公共子序列及最长公共子字符串示例攻略 什么是最长公共子序列? 两个序列 X 和 Y 的“公共子序列”,是指存在一个序列 Z,Z 中元素既在 X 中,也在 Y 中,在 X 和 Y 中出现的次序分别相同,且 Z 的长度最大。例如序列“12345”和“1245”的公共子序列有“12”、“145”等,其中“145”最长,长度为 3,即…

    Java 2023年5月26日
    00
  • throw的一些用法

    当在程序中遇到错误或异常情况时,我们可以使用 throw 语句来抛出异常。 throw 语句由 throw 关键字和要抛出的值组成,其基本语法如下: throw expression; expression 可以是任意表达式,其返回值将作为异常信息输出。 下面我们来详细讲解 throw 的一些用法: 1. 抛出预定义异常 在 C++ 中,标准库定义了一些常见…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部