認真背演算法day04

2021-10-22 07:01:52 字數 1889 閱讀 6598

好久沒更新演算法了,今天再更新一天。

今天主要複習一下trie樹和ac自動機

1.trie樹

trie 樹,是一種專門處理字串匹配的資料結構,用來解決在一組字串集合中快速查詢某個字串的問題。

trie樹的記錄方法:每乙個節點,都記錄其所有可能出現的字元,以乙個陣列形式組織,陣列中存放節點。

具體組織形式如下:

public class trie 

p = p.children[index];

}p.isendingchar = true;

} // 在trie樹中查詢乙個字串

public boolean find(char pattern)

p = p.children[index];

}if (p.isendingchar == false) return false; // 不能完全匹配,只是字首

else return true; // 找到pattern

} public class trienode

}}

簡單明瞭。

2.ac自動機

ac自動機用於文字和多模式串的匹配。

解決文字和多模式串的匹配,大家最先想到的是用kmp將每個模式串和文字進行匹配,但是這樣效率很低,從而引入ac自動機。

ac 自動機實際上就是在 trie 樹之上,加了類似 kmp 的 next 陣列,只不過此處的 next 陣列是構建在樹上罷了(叫做失敗指標)。如果**表示,就是下面這個樣子:

public class acnode 

}

關於如何構建 trie 樹,已經講過了。所以,這裡我們就重點看下,構建好 trie 樹之後,如何在它之上構建失敗指標?

假設我們沿 trie 樹走到 p 節點,也就是下圖中的紫色節點,那 p 的失敗指標就是從 root 走到紫色節點形成的字串 abc,跟所有模式串字首匹配的最長可匹配字尾子串,就是箭頭指的 bc 模式串。這裡的最長可匹配字尾子串,我稍微解釋一下。字串 abc 的字尾子串有兩個 bc,c,我們拿它們與其他模式串匹配,如果某個字尾子串可以匹配某個模式串的字首,那我們就把這個字尾子串叫作可匹配字尾子串。

構建失敗指標**:

public void buildfailurepointer()  else 

q = q.fail;

}if (q == null)

}queue.add(pc);}}}

具體查詢的過程有以下注意事項:

1.主串和多模式串進行匹配時,如果匹配到中間的某個字元失敗了,則通過失敗指標轉移

2.如果匹配到中間的某個字元a成功了,這時不能立即去匹配下乙個字元,而是應該再匹配下乙個字元之前,做以下工作:將a的失敗指標乙個乙個遍歷,然後看看是不是ending字元,如果是,則說明已經匹配到了某個短的模式串,需要列印出來。

明白了以上兩句話,可以寫出如下**:

public void match(char text) 

p = p.children[idx];

if (p == null) p = root; // 如果沒有匹配的,從root開始重新匹配

acnode tmp = p;

while (tmp != root)

tmp = tmp.fail;}}}

假如再ac自動機的樹上,某個節點的值和自己所在的模式串的首字母的值一樣時,就是kmp演算法啦。

認真背演算法day03

昨天高強度背了bm演算法和kmp演算法,今天整點陽間的休閒一下。今天主要講兩個東西,乙個是堆排序,乙個是圖的深度遍歷 回溯演算法 和廣度遍歷。堆排序為什麼堆這麼重要呢?因為堆是可以用陣列表示的,假設堆上某個節點在陣列中下標為i,則其左右孩子節點的下標為i 2和i 2 1。下面講解堆排序的思路 我看過...

認真背演算法day02(續) kmp演算法

字串匹配怎麼能少了大名鼎鼎的kmp演算法呢?概念 好字首 直到遇到壞字元為止,最長的字首子串。好字首的所有字尾子串中,最長的可匹配字首子串的那個字尾子串,叫作最長可匹配字尾子串 對應的字首子串,叫作最長可匹配字首子串 直接上思路 1.kmp演算法和bm演算法完全相反,kmp演算法採用從前到後進行比較...

day04 資料寬度

第4節 資料寬度 資料寬度 在上節課了解0和1的關係,同時計算機儲存資料,不是無限制可以儲存任意資料的,在我們現實中只儲存乙個數字的話,要麼把數字寫到本子上或記錄到腦子裡,那麼把它看成無限大的,但是在計算機中不是這樣的由於計算機受到硬體的約束,我們在儲存資料的時候它是有長度限制的。我們稱這個長度的限...