當前位置:首頁 » 操作系統 » 實現bf演算法

實現bf演算法

發布時間: 2023-10-24 10:30:53

❶ 數據結構(c++)字元串 模式匹配演算法問題,對高手來說只要寫一點點

恩,網路提問太差了 我都丟了幾次高分都沒有成功!
我估計丟了500分了不是亂答就是沒通過,分又沒有

❷ 數據結構-串的模式匹配

串的模式匹配就是子串定位操作。給定兩明虧個串s="s0 s1 ... s(n-1)"和t="t0 t1 ... t(m-1)"(其中n和m分別是串s和t的長度),在主串s中尋找子串t的過程稱為模式匹配,t稱為模式。如果在s中找到等於t的子串,則稱匹配成功,返回t在s中的首次出現的下標位置;否則匹配失敗,返回-1。

本文介紹三個串模式匹配演算法,分別是簡單回溯演算法(Brute-Force,BF演算法)、KMP演算法、KMP演算法的改進。

從主串s的第0個字元開始,與模式串t的第0個字元開始逐字元比較,不相同時回溯到模式串t的第0個和主串s的第1個字元,重新開始比較。以此類推,直到t的所有字元完成匹配,則匹配成功,否則匹配失敗。

BF演算法速度慢的原因是存在大量不必要的回溯,即在某一趟與t的匹配過程失敗後,需要返回s串開始字元的下一字元重新開始比較,這對於某些模式串t來說是不必要的。例如,若s=12123123132,t=12313,在t與12 12312 3132中加粗子序列進行比較時,在 2 處發生失配,BF演算法接下來將t與121 23123 132、1212 31231 32、12123 12313 2比較。由於t中的231、312與其開始的123並不相同,顯然t與121 23123 132、1212 31231 32的比較是不必要的。

KMP演算法就是利用模式串中與模式串開頭部分子串的重復性來減少重復回溯,實現新一輪比較的直接跳轉。 具體來說,KMP演算法利用一個數組記錄模式串中每一個字元前面有幾個字元與模式串從頭重復,在與s串比較失配時,直接跳轉到重復子串的下一個字元繼續比較,而不用跳轉至模式串t的第0個字元。

演算法步驟: ①計算跳轉數組next。②利用KMP演算法進行模式匹配。

next數組通過遞推計算,即如果當前字元 t[j] 的前一個字元 t[j-1] 與其 next[j-1] 指向的字元 t[next[j-1]] 相同,意味著 t[j] 前的 next[j-1]+1 個字元與從 t[0] 到 t[next[j-1]] 的子串相同,因此 next[j]=next[j-1]+1 ;如果不相同,則遞推至 t[next[j-1]] 的next值指向的字元,與 t[j-1] 比較,直到確認 t[j] 前與 t 串從頭重復的數羨字元數,或者無重復字元標記為薯槐拍 0 。

注意此處的函數返回參數類型為int*,用於 返回一位數組 ,且返回的這個一位數組必須在函數中用static定義。

KMP演算法進行模式匹配時,只需在回溯時將 j 指針賦值為 next[j] 。需要注意的是,若 next[j] 為 -1 ,則意味著 t[j] 前面沒有與 t 從頭重復的字元,且 t[j] 與 s[i] 失配,則 i 和 j 均加 1 。

考慮更特殊的模式串,還能進一步減少不必要的回溯次數。例如,s=111211112,t=11112,按照上述next的計算方式,next={-1,0,1,2,3}。當 i=3, j=3 時失配,此時 s[i]=2, t[j]=1 ,由於 next[j]=2 ,於是 j 跳轉為 2 ,t=11 1 12與s=111 2 11112比較。由於 t[next[j]]=t[j] 也為 1 ,必然與 s[i]=2 不相同,顯然這次回溯也不必要。

總結來說, 當失配的字元與待跳轉的字元相同時,跳轉一步並無意義,可再跳一步 ,即將當前字元置為跳轉後字元的next值。

❸ Java編程實現字元串的模式匹配

傳統的字元串模式匹配演算法(也就是BF演算法)就是對於主串和模式串雙雙自左向右,一個一個字元比較,如果不匹配,主串和模式串的位置指針都要回溯。這樣的演算法時間復雜度為O(n*m),其中n和m分別為串s和串t的長度。

KMP 演算法是由Knuth,Morris和Pratt等人共同提出的,所以成為Knuth-Morris-Pratt演算法,簡稱KMP演算法。KMP演算法是字元串模式匹配中的經典演算法。和BF演算法相比,KMP演算法的不同點是匹配過程中,主串的位置指針不會回溯,這樣的結果使得演算法時間復雜度只為O(n+m)。

❹ 字元串匹配演算法的使用(未完待整理)

字元串的匹配在Java中都知道使用indexOf函數來實現,那麼其匹配演算法是怎麼樣的呢?

單模式和多模式的區別就是一次遍歷主串能否將多個模式的字元串都查找出來。

英文全稱為Brute Force,暴力匹配演算法,匹配字元串的方法比較暴力,也比較簡單易懂。其大概的思路就是:

我們可以看到,在極端情況下,在主串 aaaa...aab 中尋找模式串 aab ,那麼總共需要尋找(n-m+1)次,且每次都需要比對m次,那麼時間復雜度將是 (n-m+1)*m ,即 O(n*m) ;但實際上並不會這么低效,因為我們的使用場景中主串和模式串都不會太長,而且在每個子串和模式串進行比對時,只要中途有一個不匹配,那麼當前比對就會提前結束,因此大部分情況下,時間復雜度都會比 O(n*m) 要好。

我們在BF演算法的基礎上引入哈希演算法,我們不需要將每個子串與模式串逐個字元地進行比較,而是計算得出每個子串的hash值,然後和模式串的hash值進行比較,如果有相等的,那就說明有子串和模式串匹配上了。

雖然我們只需要比對模式串和子串的hash值就能得到匹配結果,次數為(n-m+1),但是對每個子串進行hash計算的時候,是要遍歷每個字元的,因此次數也是m,那麼總的時間復雜度還是 O(n*m) ,並沒有明顯地提升。

那麼我們該如何想出一個辦法,使得每個子串hash值的計算時間得到提升呢?這就是RK演算法的精髓,假設子串包含的字元集中元素個數為k,那麼就用k進制數來代表這個子串,然後hash的過程就是將這個k進制的數轉換為十進制的數,這個十進制的數就是該子串的hash值。

相鄰子串的hash值計算是有規律的,我們只需要遍歷一次主串就能得到所有子串的hash值,演算法復雜度為O(n),而不是像原先一樣,每個子串都需要O(m)的時間復雜度。

然後將模式串的hash值和所有子串的hash值進行比較,每次比較的時間復雜度是 O(1) ,總共比較(n-m+1)次,所以RK演算法的總的時間開銷為 O(n)+O(1)*O(n-m+1) ,即為 O(n) ,時間復雜度比BF演算法更加高效。

當然,有hash的地方就有可能會存在hash沖突,有可能子串和hash值和模式串的hash值是一樣的,但內容就是不一樣,此時怎麼辦呢?其實很簡單,對於hash值一樣的子串,我們增加雙保險,再比較一下這m個字元是否都一樣即可,總的時間開銷為 O(n)+O(1)*O(n-m+1)+O(m) ,即為 O(n) 。

如果極端情況下出現了很多hash沖突呢?我們對於每個和模式串相同hash值的子串都需要逐一再進行比較,那麼總的時間開銷就會為 O(n)+O(1)*O(n-m+1)+O(m)*O(n-m+1) ,即為 O(n*m) ,不過這種概率太小了,大部分情況下都不會這樣。

在真正的文本編輯器中查找和替換某個字元串時,使用的演算法既不是上述的BF演算法,也不是RK演算法;BF演算法只適合不是很長的主串,RK演算法則要設計一個沖突概率很低的hash演算法,這個比較困難,所以實際使用的是BM演算法,它是工程中非常常用的一種字元串匹配演算法,效率也是最高的。

演算法的思想和過程有些復雜,待以後整理。

KMP演算法在本質上是和BM演算法一樣的。演算法的思想和過程有些復雜,待以後整理。

瀏覽器輸入框中的智能輸入匹配是怎麼實現的,它是怎麼做動態字元串匹配查找的呢?這就用到了Trie樹。

又名字典樹,是一種專門用來快速查找字元串前綴匹配結果的樹形結構,其本質就是將所有字元串的重復的前綴合並在一起,構造一個多叉樹。

其中,根節點不包含任何信息,每個節點表示一個字元,從根節點到紅色節點的一條路徑表示存儲的一個字元串。當我們在如上Trie樹中查找"he"時,發現"he"並非是一個字元串,而是"hello"和"her"的公共前綴,那麼就會找到這兩個字元串返回。

Trie樹在內存中是如何存儲的呢?因為每一個節點都可能是包含所有字元的,所以每一個節點都是一個數組(或者散列表),用來存儲每個字元及其後綴節點的指針。

使用Trie樹,最開始構建的時候,時間復雜度為 O(n) ,其中n為所有字元串長度之和,但是一旦構建完成,頻繁地查詢某個字元串是非常高效的,時間復雜度為 O(k) ,其中k為查找字元串的長度。

Trie樹雖然查詢效率很高,但是比較浪費內存,每一個節點都必須維護一個數組存放所有可能的字元數據及其指向下一個節點的指針,因此在所有字元串公共前綴並不多的時候,內存空間浪費地就更多了。這種問題其實也有對應的解決辦法,我們可以不使用數組,而是使用有序數組、散列表、紅黑樹來存放,可以相應地降低性能來節省內存空間。

Trie樹除了可以實現瀏覽器動態輸入內容查找候選項的功能外,還可以實現多模式地敏感詞匹配功能。假設我們需要對用戶輸入的內容進行敏感詞檢查,將所有的敏感內容用***代替,那麼該如何實現呢?

首先我們可以維護一個敏感詞字典,使用上述四種單模式匹配演算法也可以實現,但是需要遍歷N次用戶輸入的內容,其中N是所有敏感詞的模式串,顯得非常低效。但是我們如果將敏感詞字典維護為一個Trie樹,然後將用戶輸入的內容從位置0開始在Trie樹中進行查詢,如果匹配到紅色節點,那麼說明有敏感詞;如果沒有匹配到紅色節點,就從用戶輸入內容的下一個位置開始繼續在Trie樹中查詢,直至將用戶輸入內容遍歷完,因此我們只是遍歷了一遍主串。

然而更高效的多模式字元串匹配使用地更多的是如下的AC自動機。

如果把Trie樹比作BF演算法,KMP演算法是BF演算法的改進,那麼AC自動機就是利用同樣的思想改進了Trie樹。

演算法的思想和過程有些復雜,待以後整理。

❺ 串的模式匹配演算法

本文主要講述了串的模式匹配演算法,包括BF演算法、RK演算法、KMP演算法、BM演算法,使用不同的演算法實現目標串查找子串,重點在於分析的過程,通過不同的演算法分析提高邏輯思維能力

模式匹配的目的就是在目標串中查找與模式串相等的子串。在這里稱呼主串為s,模式串為t,主串的長度為n,模式串的長度為m

暴力演算法,將目標串和模式串的每個字元都進行一一比較。性能最差,但是使用最廣,因為實現簡單,而且在字元串較小的情況下耗費的性能也很小。

O(n*m)

RK演算法把字元串比較問題,轉換為了Hash值比較問題。
將模式串t的每個字元的比較改成了將串作為整體與目標串進行哈希值比較,這樣就減少了比較次數
以前模式串與子串的比較需要比較每個字元,現在只要整體比較依次哈希值就可以。所以減少了比較次數。

哈希演算法

這里我們可以發現一個Hash沖突問題,比如"abc"和"bc"的Hash值是一樣的,因為最高位是0。所以還需要進行哈希沖突演算法。

哈希沖突演算法:

利用前一個結果計算下一個哈希值
這是因為目標串的相鄰子串,其實相差的只有第一個字元和最後一個字元,其他字元是相同的,
所以我們可以利用前一個計算結果減去前一個字元串的第一個字元串,加上這個字元串的最後一個字元就夠了。

針對BF的弊端,在KMP演算法中可以進行多字元的跳躍對比,以此來避免目標串的不必要回溯。

例子:

簡單說明一下:

真子串:

匹配:

例如:目標串:"abxabcabcaby",模式串:"abcaby"

模式串的最大真子串為ab,
我們在匹配時,發現目標串的子串abcabc與模式串的前字元都匹配,最後一個字元不匹配
所以就從目標串的abcabc的後面abc開始與模式串進行匹配,而不需要匹配前面的abc了。

也就是從上一個a字元直接跳躍到了下一個a字元,而不是從b字元開始。

會存在一種情況:

實現思想:

它是一種非常高效的字元串匹配演算法,有實驗統計,它的性能是著名的KMP演算法的三四倍。BM演算法的原理很多復雜,比較難懂,學起來比較燒腦。
實現思想和KMP演算法基本上是一樣的,都是先計算模式串的真子串,之後再查找真子串的大小,當出現不匹配時,直接在真子串後進行匹配,區別於KMP演算法,它是從後往前匹配的

這里比上面的KMP演算法增加了一個壞字元規則,可以更快的跳躍,當然KMP演算法本身也可以使用壞字元規則

壞字元規則

好後綴規則

❻ 關於BF演算法的C語言實現

我修改的程序都是把S[0] T[0]轉換為strlen(S) strlen(T)函數來實現的
為什麼不把strlen(S),strlen(T)分別賦予S[0],T[0],害怕覆蓋原來的數據嗎?沒有必要,他們原本就是來存儲這個數據的,君不見,它們都不參與匹配!他們的初始化應該在這個函數之外完成,在每次數組長度改變後,就及時設置,換句話說,在調用這個函數之前,應該保證他們已經設置正確,
在列印時,應該從第二個元素S[1]或T[1]開始,因為S[0],T[0]不再是數組的實際內容
不知道我有沒有表述清楚,
一般,數組的第一個元素存放實際的內容,而你這里並不是這樣,數組的第一個元素不再是數組的實際內容,而是數組長度
==================================================================
補充;
比較大小時S[0]的值不就變成了整形的ASCII碼值了么?
1.整數就是整數,沒有ASCII碼,ASCII碼是針對字元的
2.在C中,整數賦予字元變數是合法的
2.在C中,字元與整數的關系運算也是合法的,當你要把一個位元組的數解釋成字元的時候,它就是字元,可他存儲的還是數啊,就把它當整數用吧,畢竟我們沒有打算列印它,當然它能表示的整數太少了,所以數組長度受到限制
如果你要以字元顯示它,那它當然是那個整數所對應的字元,如果那是可列印字元的話

熱點內容
ipad訪問google 發布:2024-11-30 18:33:13 瀏覽:696
360怎麼修改密碼 發布:2024-11-30 18:33:07 瀏覽:167
英雄之城源碼 發布:2024-11-30 18:27:03 瀏覽:440
培養人的腳本 發布:2024-11-30 18:03:54 瀏覽:255
wapphp源碼 發布:2024-11-30 18:02:37 瀏覽:516
濟南獲取網路時間伺服器地址 發布:2024-11-30 17:51:39 瀏覽:924
vivo忘記賬戶密碼怎麼辦 發布:2024-11-30 17:49:44 瀏覽:811
java上傳ftp時500 發布:2024-11-30 17:47:31 瀏覽:213
dnf配置打團卡是怎麼回事 發布:2024-11-30 17:46:42 瀏覽:658
為什麼搜不到麒麟9000的緩存 發布:2024-11-30 17:10:11 瀏覽:250