好久沒更新演算法了,今天再更新一天。
今天主要複習一下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的關係,同時計算機儲存資料,不是無限制可以儲存任意資料的,在我們現實中只儲存乙個數字的話,要麼把數字寫到本子上或記錄到腦子裡,那麼把它看成無限大的,但是在計算機中不是這樣的由於計算機受到硬體的約束,我們在儲存資料的時候它是有長度限制的。我們稱這個長度的限...