1. 程式人生 > >從零開始學習字符串算法

從零開始學習字符串算法

嘗試 noip 實現 部分 固定 方式 考過 資料 source

前言

字符串算法是OI中非常重要的一個部分,盡管在筆者的印象中NOIP未曾考過,但在省選及NOI甚至更高水平的比賽上幾乎逢考必出。

同時,目前在論文、網站、博客、書籍等各類資料上,很少能找到系統而全面地學習一整個知識點的方法和學習過程。

綜上,筆者嘗試采用一種以時間為軸的全新方式記錄從零開始學習字符串算法的整個過程,供讀者參考。

筆者認為,學習字符串算法,如果以每天學習6個小時以上來計算,按照本文所述的學習過程,20天可以實現從零到省選水平的質的飛躍。

筆者希望本文能幫助到讀者,也期待讀者提出寶貴的建議和意見。


Day 0

準備日

前置知識點:C++語言、Hash思想

學習知識點:

第一階段(8天):字符串Hash、KMP模式匹配算法、Trie(字典樹)、AC自動機

第二階段(12天):馬拉車(manacher) 算法、回文自動機、後綴數組、後綴自動機


Day 1

學習:字符串Hash

摘自《算法競賽進階指南》(李煜東)

下面介紹的字符串Hash函數把一個任意長度的字符串映射成一個非負整數,並且其沖突的概率幾乎為零。

取一固定值\(P\),把字符串看作\(P\)進制數,並分配一個大於\(0\)的數值,代表每種字符。一般來說,我們分配的數值都遠小於\(P\)。例如,對於小寫字母構成的字符串,可以令\(a=1,b=2,\cdots,z=26\)取一固定值\(M\),求出該\(P\)進制數對\(M\)的余數,作為該字符的Hash值。

一般來說,我們取\(P=131\)

\(P=13331\),此時Hash值產生沖突的概率極低,只要Hash值相同,我們就可以認為原字符串是相等的。通常我們取\(M=2^{64}\),即直接使用unsigned long long類型存儲這個Hash值,在計算時不處理算術溢出問題,產生溢出時相當於自動對\(2^{64}\)取模,這樣可以避免低效的取模(mod)運算。


參考資料

李煜東《算法競賽進階指南》(買書地址:京東、淘寶)

從零開始學習字符串算法