leetcode刷題總結——字符串匹配

KMP(字符串匹配算法)

主串或目標串:比較長的,我們就是在它里面尋找子串是否存在;

子串或模式串:比較短的。

前綴:字符串A和B,A = B+S,S非空,則B為A的前綴。

后綴:A = S+B,S非空,則B為A的后綴。

PMT:前綴集合和后綴集合的交集中,最長前綴的長度。

部分匹配表:PMT值集合,字符串的所有前綴的PMT值。
在這里插入圖片描述

當出現失配的字符時,我們原來的暴力算法需要將目標串逐個后移,這個過程其實就是拿已經匹配部分的前綴去逐個匹配后綴。如果我們能夠知道每一個位置i處,S[0:i]中已經和后綴匹配的前綴,那么我們是不是就可以直接將前綴和后綴對齊,進而跳過了中間一些字符,然后直接去比較模式串i+1處的字符呢?答案是肯定的。

KMP.drawio.png

圖中綠色塊,就是構建next數組過程中,隨著遍歷的深入,前綴和后綴的匹配情況。

其實,我們換一個方向去思考或許更容易:

例如紅色A處失配,那么我們就將目標串往后移動,我們希望移動到模式串的前綴當前已經遍歷到的目標串的后綴匹配字符最多的地方。

我們需要一個next數組記錄目標串的當前位置失配時,模式串應該轉跳的位置。

next數組與模式串對應。并且next[0] = -1,表示第一個字符沒有匹配的前后綴,如果在0位置失配,只能將目標串后移一位,去和模式串的第二位進行匹配。

next數組中如果某一個元素值為-1,其實就是表示模式串當前位置沒有匹配的前綴,如果在這個位置失配,那么應該直接將目標串的第一位和模式串的下一位比較。

next數組的構造,是通過模式串自己的前綴和后綴匹配進行的。

next[0]=-1;
// 初始化next數組
int i=0,j=-1;//i指向目標串,j指向模式串
while(i<ch.length){if(j==-1){// j=-1,說明,與i匹配的地方是空,那么也就說明,模式串已經到開頭了// 但是還是和目標串不匹配// abab bab b和a不匹配,我們應該將i后移再和j匹配。i+=1;j+=1;}if(ch[i]==ch[j]){i+=1;j+=1;// 當前位置匹配,next[i]的值等于當前位置之前的字符串的PMTnext[i]=j;}else{// 當前位置不匹配,對模式串進行轉跳,// next[j]表示如果在當前位置失配,就應該將模式串的索引轉跳到next[j]位置,繼續匹配j=next[j];}
}

next[i]數組的值表示匹配串的i位置失配了,那么就應該拿模式串的前綴繼續和當前位置匹配,即轉跳到next[i]位置,繼續判斷是否匹配。

public static int KMP(String Str,String Sub,int pos){if (Str == null || Sub == null){return -1;}int i = pos, j = 0;int[] next = new int[Sub.length()];getNext(next,Sub);while(i < Str.length() && j < Sub.length()){if (j == -1 || Str.charAt(i) == Sub.charAt(j)){i++;j++;}else {j = next[j];}}if (j >= Sub.length()){return i-j;}else {return -1;}
}
public static void getNext(int[] next,String sub){next[0] = -1;next[1] = 0;int i = 2,k = 0;while(i < next.length){if (k ==- 1 || sub.charAt(k) == sub.charAt(i-1)){next[i] = k+1;i++;k++;}else {k = next[k];}}
}

示例一

459. 重復的子字符串

/*** 方法一:枚舉法,由于子串至少有兩個,因此,我們枚舉子串的長度1<=k<=n//2;* 方法二:KMP算法,首先先證明一個原理* 假設s的子串為c,且為4個,那么s可以表示為     ccccc* 如果我們將第一個c移動到末尾,那么應該還可以組成s。* 基于這個原理,我們將s復制一份,變成 ss,如果我們刪除ss的第一個字符和最后一個字符* 如果s存在子串c,那么,ss經過刪除前后兩個字符后,中間部分一定還存在和s匹配的字符串*/

示例二

1392. 最長快樂前綴

/*** 思路:kmp算法,首先需要得到字符串s的next數組* 然后,根據題意可知,快樂前綴是和后綴匹配的。那么我們就需要知道,next數組中最后一個位置的數值pos* pos表示,s最后一個數對應的轉跳位置,然后,我們需要進一步比較s[pos]是否等于s[-1]:*   a. 等于,則找到了最長的快樂前綴;*   b. 不等于,pos位置失配,繼續轉跳pos=next[pos];* 直到s[pos]==s[-1]或者pos==-1為止。*/

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

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

相關文章

婚禮成本與籌備策略:一場夢幻婚禮的理性規劃

婚禮成本與籌備策略&#xff1a;一場夢幻婚禮的理性規劃 摘要 婚禮&#xff0c;作為人生中的重要儀式&#xff0c;承載著新人的愛情與夢想&#xff0c;同時也伴隨著不菲的經濟投入。本文旨在探討婚禮所需的大致成本、影響成本的主要因素以及婚禮籌備過程中的關鍵注意事項&…

【Java--數據結構】二叉樹

歡迎關注個人主頁&#xff1a;逸狼 創造不易&#xff0c;可以點點贊嗎~ 如有錯誤&#xff0c;歡迎指出~ 樹結構 樹是一種非線性的數據結構&#xff0c;它是由n&#xff08;n>0&#xff09;個有限結點組成一個具有層次關系的集合 注意&#xff1a;樹形結構中&#xff0c;子…

Transformer模型在多任務學習中的革新應用

在深度學習領域&#xff0c;多任務學習&#xff08;Multi-task Learning, MTL&#xff09;是一種訓練模型以同時執行多個任務的方法。這種方法可以提高模型的泛化能力&#xff0c;因為它允許模型在不同任務之間共享知識。近年來&#xff0c;Transformer模型因其在自然語言處理&…

【linux高級IO(三)】初識epoll

&#x1f493;博主CSDN主頁:杭電碼農-NEO&#x1f493; ? ?專欄分類:Linux從入門到精通? ? &#x1f69a;代碼倉庫:NEO的學習日記&#x1f69a; ? &#x1f339;關注我&#x1faf5;帶你學更多操作系統知識 ? &#x1f51d;&#x1f51d; Linux高級IO 1. 前言2. 初識e…

STM32 HRTIM生成PWM時遇到無法輸出PWM脈沖波形問題

在使用HRTIM生成PWM時&#xff0c;當把周期寄存器更新的設置放到while循環中時&#xff0c;無法輸出PWM脈沖波形&#xff0c;即使增加計數延時也無法輸出&#xff0c;最終只能放到中斷函數中執行后期寄存器值更新才能夠生成PWM脈沖波形。

主流大數據調度工具DolphinScheduler之數據ETL流程

今天給大家分享主流大數據調度工具DolphinScheduler&#xff0c;以及數據的ETL流程。 一&#xff1a;調度工具DS 主流大數據調度工具DolphinScheduler&#xff0c; 其定位&#xff1a;解決數據處理流程中錯綜復雜的依賴關系 任務支持類型&#xff1a;支持傳統的shell任務&a…

Python學習4---迭代器和生成器的區別

一、迭代器 定義&#xff1a;迭代器是一個可以記住遍歷的位置的對象。迭代器對象必須實現兩個方法&#xff0c;iter() 和 next()。字符串、列表或元組等數據類型都是可迭代對象&#xff0c;但它們不是迭代器&#xff0c;因為它們不具有 next() 方法。迭代器對象用于遍歷可迭代對…

冷卻塔由那些配件組成

1、淋水填料 將需要冷卻的水&#xff08;熱水&#xff09;多次濺灑成水滴或形成水膜&#xff0c;以增加水和空氣的接觸面積和時間&#xff0c;促進水和空氣的熱交換。 填料在開式橫流冷卻塔的作用是增加循環水與空氣的接觸面積&#xff0c;并延長冷卻水停留在空氣中的時間&am…

LabVIEW工業設備姿態監測系統

開發了一種基于LabVIEW的工業設備姿態監測系統&#xff0c;針對現有監測設備在適應性和反應時間上的不足&#xff0c;采用了LabVIEW軟件和STM32微控制器&#xff0c;通過高精度姿態傳感器實現了對設備姿態的快速準確監測&#xff0c;大大提高了工業作業的安全與效率。 項目背景…

C++深度解析教程筆記9-靜態成員變量,靜態成員函數,二階構造,友元,函數重載,操作符重載

C深度解析教程筆記9 第25課 - 類的靜態成員變量實驗-數對象個數&#xff08;失敗&#xff09;實驗-靜態變量小結 第26課 - 類的靜態成員函數實驗-修改對象的靜態變量數值實驗-利用靜態成員函數實驗-靜態變量靜態函數實現統計對象個數小結 第27課 - 二階構造模式實驗-初始化是否…

百度人臉識別Windows C++離線sdk C#接入

百度人臉識別Windows C離線sdk C#接入 目錄 說明 設計背景 ? 場景特點&#xff1a; ? 客戶特點&#xff1a; ? 核心需求&#xff1a; SDK 包結構 效果 代碼 說明 自己根據SDK封裝了動態庫&#xff0c;然后C#調用。 功能接口 設計背景 ? 場景特點&#xff1a; -…

【滲透入門】XSS

文章目錄 XSS漏洞XSS舉例XSS類型防御方式 XSS漏洞 XSS&#xff08;Cross-Site Scripting&#xff0c;跨站腳本攻擊&#xff09;是一種常見的Web應用程序安全漏洞。XSS漏洞發生在應用程序未能充分過濾用戶提供的數據&#xff0c;使得惡意腳本得以在不知情的用戶的瀏覽器中被執行…

ARFoundation系列講解 - 91 Immersal 簡介

一、Immersal 簡介 Immersal是一家專注于增強現實(AR)技術的公司,致力于開發和推廣空間感知解決方案(簡稱:大空間技術)。他們的核心產品是一個名為Immersal SDK的開發工具包,通過視覺定位(VPS)能夠輕松地在現實世界中實現高精度的定位和增強現實體驗。 二、Immersal …

Spring Boot集成Knife4j:實現高效API文檔管理

Spring Boot集成Knife4j&#xff1a;實現高效API文檔管理 在軟件開發過程中&#xff0c;編寫和維護接口文檔是一項必不可少的任務。隨著微服務架構的流行&#xff0c;API文檔的重要性日益凸顯。然而&#xff0c;傳統的手動編寫文檔方式不僅效率低下&#xff0c;而且容易出錯。…

支持前端路由權限和后端接口權限的企業管理系統模版

一、技術棧 前端&#xff1a;iview-admin vue 后端&#xff1a;springboot shiro 二、基于角色的權限控制 1、路由權限 即不同角色的路由訪問控制 2、菜單權限 即不同角色的菜單列表展示 3、按鈕權限 即不同角色的按鈕展示 4、接口權限 即不同角色的接口訪問控制 三…

數字化時代的生產革新:數字孿生平臺如何助力新質生產力

一.新質生產力 在當今快速發展的科技和信息時代&#xff0c;企業和組織在提高生產效率和質量方面面臨著越來越多的挑戰和機遇。新質生產力的概念應運而生&#xff0c;強調通過創新和技術進步&#xff0c;不僅提升生產的數量和速度&#xff0c;更重要的是優化生產方式、改善產品…

leetcode熱題100.分割等和子集(動態規劃)

分割等和子集 Problem: 416. 分割等和子集 思路 我選擇使用動態規劃的方法來解題。我們需要判斷是否可以將數組分割成兩個子集&#xff0c;使得這兩個子集的和相等。這個問題可以轉化為在數組中找到一個子集&#xff0c;使得其和等于數組總和的一半。 解題過程 首先&#xf…

消息隊列-RocketMQ

消息隊列-RocketMQ 1、RocketMQ是什么?2、RocketMQ有什么優缺點?3、消息隊列主要有哪幾種消息模型?4、RocketMQ主要使用哪種消息模型?5、RocketMQ的基本架構是怎樣的?有哪些核心組件?6、RocketMQ通過什么方式保證消息的可用性和可靠性?7、什么情況下會發生消息丟失?Roc…

設計模式大白話之裝飾者模式

想象一下&#xff0c;你走進一家咖啡館&#xff0c;點了一杯美式咖啡。但是&#xff0c;你可能還想根據自己的口味添加一些東西&#xff0c;比如奶泡、巧克力粉、焦糖醬或是肉桂粉。每次你添加一種配料&#xff0c;你的咖啡就會變得更豐富&#xff0c;同時價格也會相應增加。 在…

圖——圖的應用02最短路徑(Dijkstra算法與Floyd算法詳解),拓撲排序及關鍵路徑

前面介紹了圖的應用——01最小生成樹章節&#xff0c;大家可以通過下面的鏈接學習&#xff1a; 圖——圖的應用01最小生成樹&#xff08;Prim算法與Kruskal算法詳解&#xff09; 今天就講一下圖的其他應用——最短路徑&#xff0c;拓撲排序及關鍵路徑。 目錄 一&#xff0c…