【算法篇】KMP算法,一種高效的字符串匹配算法

我們今天了解一個字符串匹配算法-KMP算法,內容難度相對來說較高,建議先收藏再細品!!!
在這里插入圖片描述

KMP算法的基本概念

KMP算法是一種高效的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人們稱它為克努特—莫里斯—普拉特操作(簡稱KMP算法)。

該算法的主要使用場景就是在字符串(也叫主串)中的模式串(也叫字串)定位問題,常見的有“求子串出現的起始位置”、“求子串的出現次數”等。

解決什么問題

假設有兩個字符串,分別為文本串和模式串,如下:


求在文本串中是否出現過上面的模式串。

暴力解法

當出現不匹配的字符時,暴力算法會進行如下兩個操作:

  • 向后移動模式串
  • 目標串和模式串的指針都回溯

KMP優化解法

使用暴力算法的時間復雜度較高,如何去優化呢?

優化方向:防止或減少主串指針回溯

當出現不匹配的字符時,目標串指針不動,只移動模式串。

移動前,指針左邊的字符已經匹配了,所以要讓移動后的目標串的指針不會蘇,需要保證:模式串移動之后,在指針左邊的字符也是匹配的。

  • 找相同字符必須是從模式串第一個位置開始
  • 模式串移動方式由能找到的最長的相同字符決定,如果不是最長的,可能會漏掉能匹配的內容。
  • 找到的最長的相同字符串長度必須小于已經匹配的內容長度,前后部分可以有交叉內容

KMP算法小結

  • 發生不匹配時,指針所指的下標等于已經匹配的長度
  • 發生不匹配時,需要移動的長度 = 已經匹配的長度 - 前后相同的最大長度
  • 前后相同的最大長度為空的地方用-1補齊

KMP算法中的next數組

當目前的C和A不匹配時,由于A的前面也全都是A,所以前面也一定不匹配,對于這個模式串,可以直接將指針移動到-1的位置。

所以需要再對next數組進行改進,改進后的數組我們命名為nextval。

優化next數組

總結:若str[j] == str[next[j]],那么nextval[j] = nextval[next],否則nextval[j] = next[j]

判斷是否匹配

先給定兩個字符串,分別表示文本串和模式串,通過kmp(稍后寫這個函數)進行比較,找到第一次出現模式串的位置,如果沒有匹配上則給出提示。

char *text = "aaaaaabaaa",*pattern = "aaaab";
int index = kmp(text,pattern);
if(index == -1)
{cout << "沒有匹配上內容";
} 
else{cout << "匹配上了,起始位置為:" << index;
}

輸出next數組

next指針用來動態獲取模式串的長度

int kmp(char *text,char *pattern){int index = -1;int txt_len = strlen(text),ptn_len = strlen(pattern);int *next = (int *)malloc(sizeof(int) * ptn_len);get_next(pattern,next,ptn_len);free(next);return index;
}

計算next數組

若str[j] == str[k]時,next[j+1] = k+1
若str[j] != str[k]時,k = next[k]

void get_next(char *str,int *next,int len){int j = 0,k = -1;next[0] = -1;while(j < len-1){if(k == -1 || str[j] == str[k]){k++;j++;next[j] = k;}else k = next[k];} 
}

遍歷輸出next數組

從下標為0的位置到ptn_len依次輸出next數組內的元素

int kmp(char *text,char *pattern)
{int index = -1;int txt_len = strlen(text),ptn_len = strlen(pattern);int *next = (int *)malloc(sizeof(int) * ptn_len);get_next(pattern,next,ptn_len);for(int i=0;i<ptn_len;i++){printf("%d ",next[i]);}free(next);return index;
}

輸出nextval數組

將next數組變為nextval數組(此處的next數組實際上是nextval數組)

if(k == -1 || str[j] == str[k]){k++;j++;if(str[j] == str[k]){next[j] = next[k];}else{next[j] = k;}
}
else{k = next[k];
} 

輸出匹配位置

int index = -1,txt_idx = 0,ptn_idx = 0;
... ...
get_next(pattern,next,ptn_len);while((txt_idx < txt_len) && (ptn_idx < ptn_len))
{if(text[txt_idx] == pattern[ptn_idx] || ptn_idx == -1){txt_idx++;ptn_idx++;}else{ptn_idx = next[ptn_idx];}
}if(ptn_idx >= ptn_len){index = txt_idx - ptn_len;
}

利用KMP算法解決字符串匹配問題,能極大節約時間復雜度。關于KMP算法還有什么問題的話,歡迎各位留言交流~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43178.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43178.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43178.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LLMs之gptpdf:gptpdf的簡介、安裝和使用方法、案例應用之詳細攻略

LLMs之gptpdf&#xff1a;gptpdf的簡介、安裝和使用方法、案例應用之詳細攻略 目錄 gptpdf的簡介 1、處理流程 第一步&#xff0c;使用 PyMuPDF 庫&#xff0c;對 PDF 進行解析出所有非文本區域&#xff0c;并做好標記&#xff0c;比如: 第二步&#xff0c;使用視覺大模型&…

離婚后,孩子就讀私立高中的高昂學費誰承擔?

江蘇省南京市六合區人民法院審結一起撫養費糾紛案件&#xff0c;認定夫妻雙方在決定孩子教育事務上均存在責任&#xff0c;為保障臨近高考的未成年子女的切身利益&#xff0c;認定由夫妻雙方按比例承擔教育費。   2015年6月&#xff0c;李某與王某離婚&#xff0c;雙方之子小…

PCL 有序點云的法線估計(使用積分圖進行法線估計)

使用積分圖進行法線估計 一、概述1.1 概念1.2 有序點云與無序點云1.2.1 有序點云1.2.2 無序點云1.3 代碼講解二、代碼實現三、結果示例一、概述 1.1 概念 使用積分圖進行法線估計:計算一個有序點云的法線,注意該方法只適用于有序點云。 1.2 有序點云與無序點云 有序點云與無…

MySQL安裝時initializing database失敗

問題頁面&#xff1a; 解決方法&#xff1a; 1.勾選紅框中的選項&#xff1a; 2.將下圖紅框中全部改為英文&#xff1a; 然后一路next就可以了。

cs231n作業1——KNN

參考文章&#xff1a;assignment1——KNN KNN 測試時分別計算測試樣本和訓練集中的每個樣本的距離&#xff0c;然后選取距離最近的k個樣本的標簽信息來進行分類。 方法1&#xff1a;Two Loops for i in range(num_test):for j in range(num_train):dist X[i, :] - self.X…

vue3使用方式匯總

1、引入iconfont阿里圖庫圖標&#xff1a; 1.1 進入阿里圖標網站&#xff1a; iconfont阿里&#xff1a;https://www.iconfont.cn/ 1.2 添加圖標&#xff1a; 1.3 下載代碼&#xff1a; 1.4 在vue3中配置代碼&#xff1a; 將其代碼復制到src/assets/fonts/目錄下&#xff1…

Mysql之Using index for skip scan

一、Using index for skip scan 在 MySQL 中&#xff0c;EXPLAIN 語句用于顯示查詢執行計劃&#xff0c;幫助我們理解查詢是如何被執行的&#xff0c;以及如何優化查詢。其中&#xff0c;Extra 列提供了關于查詢執行的一些額外信息。當 Extra 列顯示 Using index for skip sca…

CF F. Alex‘s whims

原題鏈接&#xff1a;Problem - 1899F - Codeforces 題目大意&#xff1a;要求構建出一顆樹&#xff0c;多次詢問樹的葉節點之間的距離有沒有達到要求的距離&#xff0c;如果有直接輸出-1 -1 -1&#xff0c;如果沒有可以斷開一條邊和連上一條邊&#xff0c;輸出x y z&#xff…

mp4視頻太大怎么壓縮不影響畫質,mp4文件太大怎么變小且清晰度高

在數字化時代&#xff0c;我們常常面臨視頻文件過大的問題。尤其是mp4格式的視頻&#xff0c;文件大小往往令人望而卻步。那么&#xff0c;如何在不影響畫質的前提下&#xff0c;有效地壓縮mp4視頻呢&#xff1f;本文將為您揭秘幾種簡單實用的壓縮技巧。 在分享和存儲視頻時&am…

Open3D 計算點云的歐式距離

目錄 一、概述 1.1歐式距離定義 1.2作用和用途 二、代碼實現 2.1關鍵函數 2.2完整代碼 三、實現效果 3.1原始點云 3.2處理后點云 一、概述 在Open3D中&#xff0c;compute_point_cloud_distance函數用于計算兩個點云之間的距離。具體來說&#xff0c;它計算的是源點云…

【計算機網絡仿真】b站湖科大教書匠思科Packet Tracer——實驗16 路由信息協議RIP

一、實驗目的 1.驗證RIP協議的作用&#xff1b; 二、實驗要求 1.使用Cisco Packet Tracer仿真平臺&#xff1b; 2.觀看B站湖科大教書匠仿真實驗視頻&#xff0c;完成對應實驗。 三、實驗內容 1.構建網絡拓撲&#xff1b; 2.驗證RIP協議。 四、實驗步驟 1.構建網絡拓撲 …

sdbusplus:將文件描述符作為method的返回值

sdbusplus:通過文件描述符作為參數調用method_libsdbusplus-CSDN博客 介紹了使用文件描述符作為參數的方式 文件描述符也可以作為method的返回值,然后用來傳遞數據 服務器端: //s.cpp #include <sdbusplus/asio/connection.hpp> #include <sdbusplus/asio/object…

js list to tree

在JavaScript中&#xff0c;將列表轉換為樹結構是一種常見的操作&#xff0c;尤其是在處理需要層級展示的數據&#xff0c;如菜單、分類等。這通常涉及到遞歸函數和對象的引用。以下是一個簡單的例子&#xff0c;展示了如何將一個扁平化的列表轉換為多層級樹結構。 假設我們有以…

【圖像處理】Krita 一款開源免費專業圖像處理軟件分享

軟件介紹 Krita 是一款專業級的圖像處理軟件&#xff0c;適合數字繪畫和創作。它不僅支持柵格圖像的細致編輯&#xff0c;還提供了強大的矢量圖形工具&#xff0c;使得用戶可以在同一個平臺上完成多種類型的創作工作。同時具備一定的矢量圖形編輯功能。Krita 的首要用途是繪畫…

黑馬點評商戶緩存查詢作業——Redis中查詢商戶類型

記錄下自己在gpt幫助下完成的第一個需求~~~ 1. ShopTypeController 2. IShopTypeService 3. ShopTypeServiceImpl&#xff08;模仿ShopServiceImpl來寫的&#xff09; 一共分為“1.redis中查詢緩存”→“2.判斷緩存是否存在&#xff0c;存在直接返回”→“3.緩存不存在則去查數…

2-28 基于matlab提取出頻域和時域信號的29個特征

基于matlab提取出頻域和時域信號的29個特征&#xff0c;主運行文件feature_extraction&#xff0c;fre_statistical_compute和time_statistical_compute分別提取頻域和時域的特征&#xff0c;生成的29個特征保存在生成的feature矩陣中。程序已調通&#xff0c;可直接運行。 2-2…

C語言 printf 函數多種輸出格式以及占位輸出

一、輸出格式 在C語言中&#xff0c;printf 函數提供了多種輸出格式&#xff0c;用于控制不同類型數據的輸出方式。 1.整數輸出格式 %d&#xff1a;以十進制形式輸出整數。 %o&#xff1a;以八進制形式輸出整數&#xff08;無前導0&#xff09;。 %x 或 %X&#xff1a;以十六進…

JavaScript里方括號[]的使用

我們知道可用方括號來表示數組或者JSON對象的屬性值&#xff0c;其實在特定場合&#xff0c;方括號還有妙用的。 比如我有數據源是一組JSON&#xff0c;其中有一個屬性是時間字符串&#xff0c;我想對時間的小時、星期、日、月分別進行處理。每條JSON都各自生成一條新的JSON&am…

代碼隨想三刷動態規劃篇9

代碼隨想三刷動態規劃篇9 714. 買賣股票的最佳時機含手續費題目代碼 714. 買賣股票的最佳時機含手續費 題目 鏈接 代碼 class Solution {public int maxProfit(int[] prices, int fee) {//賣的時候-feeif(prices.length1){return 0;}int[][] dp new int[prices.length][2]…

EAI四個層次服務-系統架構師(二十六)

1、&#xff08;重點&#xff09;系統應用集成提供了4個不同層次服務&#xff0c;最上層服務是&#xff08;&#xff09;服務。 解析: EAI&#xff08;Enterprise Application Integration&#xff09;系統應用集成&#xff0c;相關概念。 實施EAI必須保證&#xff1a;應用程…