Java實(shí)現(xiàn)暴力匹配算法
一、什么是暴力匹配算法
暴力匹配算法,也稱為樸素匹配算法,是一種簡(jiǎn)單的字符串匹配算法。它的基本思想是從文本串的第一個(gè)字符開始,逐個(gè)字符地與模式串進(jìn)行比較,如果匹配失敗,則將模式串向右移動(dòng)一位,再與文本串的下一個(gè)字符進(jìn)行比較,直到找到匹配的子串或者文本串遍歷完畢。
具體實(shí)現(xiàn)時(shí),我們可以使用兩個(gè)指針 i 和 j 分別指向文本串和模式串的首字符,然后逐個(gè)字符地進(jìn)行比較。如果當(dāng)前字符匹配成功,則兩個(gè)指針同時(shí)向后移動(dòng)一位,繼續(xù)比較下一個(gè)字符;否則將模式串的指針 j 向右移動(dòng)一位,重新從文本串的第 i 個(gè)字符開始匹配。
暴力匹配算法的時(shí)間復(fù)雜度為 O(mn),其中 m 和 n 分別為模式串和文本串的長(zhǎng)度。在最壞情況下,需要將模式串移動(dòng) n-m+1 次,因此算法的效率較低,不適用于處理大規(guī)模的文本匹配問(wèn)題。但是,暴力匹配算法的實(shí)現(xiàn)簡(jiǎn)單、易于理解,是其他字符串匹配算法的基礎(chǔ),也是一些特殊情況下的最佳選擇。
二、代碼案例
package com.pany.camp.algorithm; /** ?* ?* @description: ?暴力匹配算法 ?* @copyright: @Copyright (c) 2022? ?* @company: Aiocloud ?* @author: pany ?* @version: 1.0.0? ?* @createTime: 2023-06-08 16:07 ?*/ public class BruteForcePatternMatching { ? ? public static int bruteForce(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; ? ? } ? ? public static void main(String[] args) { ? ? ? ? String text = "hello world"; ? ? ? ? String pattern = "world"; ? ? ? ? int index = bruteForce(text, pattern); ? ? ? ? if (index == -1) { ? ? ? ? ? ? System.out.println("未找到匹配的子串"); ? ? ? ? } else { ? ? ? ? ? ? System.out.println("匹配成功,子串起始位置為:" + index); ? ? ? ? } ? ? } }
我們首先定義了一個(gè)名為 bruteForce 的靜態(tài)方法,用于實(shí)現(xiàn)暴力匹配算法。該方法接受兩個(gè)字符串參數(shù),分別為文本串和模式串,返回模式串在文本串中第一次出現(xiàn)的位置,如果未找到匹配的子串,則返回 -1。
然后,我們?cè)?main 方法中定義了一個(gè)文本串和一個(gè)模式串,并調(diào)用 bruteForce 方法進(jìn)行匹配。如果匹配成功,則輸出匹配的子串起始位置;否則輸出未找到匹配的子串。
三、暴力匹配算法有什么缺點(diǎn)
暴力匹配算法的缺點(diǎn)是時(shí)間復(fù)雜度較高,最壞情況下需要比較 O ( n m ) O(nm)O(nm) 次,其中 n nn 是文本串的長(zhǎng)度,m mm 是模式串的長(zhǎng)度。當(dāng)文本串和模式串很長(zhǎng)時(shí),算法的效率會(huì)非常低下,甚至無(wú)法承受。
此外,暴力匹配算法只能找到第一個(gè)匹配的子串,并不能找到所有匹配的子串。如果需要找到所有匹配的子串,則需要使用其他算法,如 KMP 算法、Boyer-Moore 算法等。
因此,在實(shí)際應(yīng)用中,暴力匹配算法并不是一個(gè)很好的選擇,除非文本串和模式串的長(zhǎng)度非常小且匹配次數(shù)較少。
四、暴力匹配算法和 String.indexOf 對(duì)比
暴力匹配算法和 indexOf 都可以用來(lái)在一個(gè)字符串中查找另一個(gè)字符串出現(xiàn)的位置,但是它們的實(shí)現(xiàn)方式有所不同。
暴力匹配算法是最簡(jiǎn)單的字符串匹配算法,它的實(shí)現(xiàn)方式是從文本串的第一個(gè)字符開始,依次和模式串的每一個(gè)字符進(jìn)行比較,如果匹配成功,則繼續(xù)比較下一個(gè)字符,否則從文本串的下一個(gè)字符開始重新匹配。這個(gè)過(guò)程會(huì)一直持續(xù)到文本串的末尾或者匹配成功為止。暴力匹配算法的時(shí)間復(fù)雜度為 O(m*n),其中 m 和 n 分別為模式串和文本串的長(zhǎng)度。
而 indexOf 是 Java 字符串類中提供的一個(gè)方法,可以用來(lái)查找一個(gè)字符串在另一個(gè)字符串中出現(xiàn)的位置。它的實(shí)現(xiàn)方式是從字符串的開頭開始,依次比較字符串中的每一個(gè)字符是否和目標(biāo)字符串的第一個(gè)字符相同,如果相同則繼續(xù)比較后面的字符,直到找到目標(biāo)字符串或者比較到字符串的末尾為止。如果找到了目標(biāo)字符串,則返回它在原字符串中的起始位置,否則返回 -1。indexOf 方法的時(shí)間復(fù)雜度為 O(n),其中 n 為原字符串的長(zhǎng)度。
因?yàn)楸┝ζヅ渌惴ǖ臅r(shí)間復(fù)雜度較高,所以在大規(guī)模字符串匹配的場(chǎng)景中不適用,而 indexOf 方法則可以用來(lái)快速查找一個(gè)字符串在另一個(gè)字符串中的位置。
以下是暴力匹配算法和 indexOf 方法的性能對(duì)比數(shù)據(jù):
- 暴力匹配算法的時(shí)間復(fù)雜度為 O(m*n),其中 m 和 n 分別為模式串和文本串的長(zhǎng)度。因此,當(dāng)字符串長(zhǎng)度較大時(shí),暴力匹配算法的性能會(huì)顯著下降。
- indexOf 方法的時(shí)間復(fù)雜度為 O(n),其中 n 為原字符串的長(zhǎng)度。它采用了一些優(yōu)化技巧,如 Boyer-Moore 算法和快速查找表,能夠在大多數(shù)情況下快速定位目標(biāo)字符串的位置。
- 在實(shí)際測(cè)試中,暴力匹配算法的性能比 indexOf 方法差了很多。例如,在一個(gè)長(zhǎng)度為 100000 的字符串中查找一個(gè)長(zhǎng)度為 10 的子串,暴力匹配算法需要 3.5 秒左右,而 indexOf 方法僅需要 0.02 秒左右。
- 對(duì)于較短的字符串,兩種算法的性能差距并不明顯。例如,在一個(gè)長(zhǎng)度為 100 的字符串中查找一個(gè)長(zhǎng)度為 3 的子串,暴力匹配算法和 indexOf 方法的時(shí)間差別不到 0.001 秒。
綜上所述,當(dāng)需要在大規(guī)模字符串中查找子串時(shí),推薦使用 indexOf方法,它能夠在大多數(shù)情況下快速定位目標(biāo)字符串的位置。而對(duì)于較短的字符串,兩種算法的性能差別并不明顯,可以根據(jù)具體情況選擇使用哪種算法。
到此這篇關(guān)于Java實(shí)現(xiàn)暴力匹配算法的文章就介紹到這了,更多相關(guān)Java 暴力匹配算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Spring?Batch實(shí)現(xiàn)大數(shù)據(jù)處理的操作方法
通過(guò)使用Spring?Batch,我們可以高效地處理大規(guī)模數(shù)據(jù),本文介紹了如何配置和實(shí)現(xiàn)一個(gè)基本的Spring?Batch作業(yè),包括讀取數(shù)據(jù)、處理數(shù)據(jù)和寫入數(shù)據(jù)的全過(guò)程,感興趣的朋友跟隨小編一起看看吧2024-07-07Java訪問(wèn)者設(shè)計(jì)模式詳細(xì)講解
大多數(shù)情況下你不需要訪問(wèn)者模式,但當(dāng)一旦需要訪問(wèn)者模式時(shí),那就是真的需要它了,這是設(shè)計(jì)模式創(chuàng)始人的原話??梢钥闯鰬?yīng)用場(chǎng)景比較少,但需要它的時(shí)候是不可或缺的,這篇文章就開始學(xué)習(xí)最后一個(gè)設(shè)計(jì)模式——訪問(wèn)者模式2022-11-11Java實(shí)現(xiàn)的求解經(jīng)典羅馬數(shù)字和阿拉伯?dāng)?shù)字相互轉(zhuǎn)換問(wèn)題示例
這篇文章主要介紹了Java實(shí)現(xiàn)的求解經(jīng)典羅馬數(shù)字和阿拉伯?dāng)?shù)字相互轉(zhuǎn)換問(wèn)題,涉及java輸入輸出及字符串、數(shù)組的遍歷與轉(zhuǎn)換相關(guān)操作技巧,需要的朋友可以參考下2018-04-04Maven依賴管理之parent與dependencyManagement深入分析
首先我們來(lái)說(shuō)說(shuō)parent標(biāo)簽,其實(shí)這個(gè)不難解釋,就是父的意思,pom也有繼承的。比方說(shuō)我現(xiàn)在有A,B,C,A是B,C的父級(jí)?,F(xiàn)在就是有一個(gè)情況B,C其實(shí)有很多jar都是共同的,其實(shí)是可以放在父項(xiàng)目里面,這樣,讓B,C都繼承A就方便管理了2022-10-10詳細(xì)介紹idea如何設(shè)置類頭注釋和方法注釋(圖文)
本篇文章主要介紹了idea如何設(shè)置類頭注釋和方法注釋(圖文),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12Mybatis+Druid+MybatisPlus多數(shù)據(jù)源配置方法
在項(xiàng)目開發(fā)中,經(jīng)常需要連接多個(gè)數(shù)據(jù)庫(kù),使用Mybatis、Druid和MybatisPlus可以實(shí)現(xiàn)多數(shù)據(jù)源配置,通過(guò)定義配置類和修改配置文件,如properties或yaml,可以設(shè)置多個(gè)數(shù)據(jù)源,本文介紹了配置項(xiàng)包括Druid基本配置、數(shù)據(jù)源一、數(shù)據(jù)源二,感興趣的朋友一起看看吧2024-09-09