算法淺談——字符串相關

我的水平所限,只能談及幾年前的OI省選水平的算法。再高深的,便不清楚了。html


主要參考文獻:git

  1. hzwer,《OI省選算法彙總》
  2. _Rayx,《多種字符串匹配算法雜談》
  3. airfer,《字符串匹配算法比較》
  4. 羅穗騫,《後綴數組——處理字符串的有力工具》
  5. xiazdong,《Dijkstra、Bellman_Ford、SPFA、Floyd算法複雜度比較》
  6. Create Chen,《理解A*尋路算法具體過程》
  7. lufy,《A*尋路算法與它的速度》
  8. Amit,蔡鴻譯,《Amit's A star Page中譯文》

OI算法,大抵可分爲如下幾類:github

  1. 數據結構
  2. 字符串相關
  3. 圖論相關
  4. 數學相關
  5. 動態規劃
  6. 計算幾何
  7. 不保證正確性的算法
  8. 其餘重要工具與方法

下面依次談一談。算法

這個算法是怎麼來的,是爲了解決什麼問題而來,之前的算法爲何沒有解決,而如今的算法卻能解決;如今這個算法還有些什麼缺點;能作一些什麼問題,不能作些什麼問題。—— Ronghua Li數組

字符串相關

單模式串匹配

  • KMP:在主串S(長度N)中匹配一個模式串P(長度M),預處理時間 O(M) ,匹配時間 O(N+M) 。數據結構

  • KMP及相關算法時間複雜度比較:函數

    其中,M爲模式串長度,N爲主串長度。
    實測時,string長度10000,每一個函數都被調用了1000次。
算法 預處理時間 匹配時間 實測時間
BF O(0) O(NM) 0.078
KMP O(M) O(N) 0.094
BM O(N+M2) O(N) 0.047
Sunday O(M) O(NM) 0.172
Robin-Karp O(0) O(NM) 0.328
Bitap O(M) O(NM)O(N) 0.281

字典樹(Trie)

Trie是一種n叉樹,n爲字母表大小,每一個節點表示從根節點到此節點所通過的全部字符組成的字符串。工具

多模式串匹配

  • AC自動機:在主串S(長度N)中匹配多個模式串P(長度M),預處理時間 O(N+Mi) ,匹配時間 O(N+Mi) 。

AC自動機就是KMP思想。但用KMP作多模式串匹配的時間複雜度是 O(N+Mi) 。顯然,提升的複雜度是 O(N(K1)) ,其中K表示模式串的個數。而當模式串數量大、模式串較短、主串較長時,算法幾乎是從 O(N2) 降到了 O(N) 。ui

還有一種多模式的匹配算法叫作AC自動機。它能一次匹配多個模式串。它與KMP的思路很像,不匹配時找一個最長的再繼續進行!它須要先把字符串建成一顆Trie樹,樹結點有一個叫作failed的指針,是表示若是不匹配時應該再從哪一個結點進行匹配。由於這種作法是一種DFA上的匹配,而發明這種算法的人叫A.C.,因此就叫AC自動機了。複雜度很好,比每一個模式串用一次KMP算法要好不少。atom

後綴樹、後綴數組

  • 這倆是很是有用的字符串處理工具,尤爲是後綴數組,不少複雜字符串問題均可以用它來快速完美解決。
  • 構造:倍增算法 O(logN) ,DC3算法 O(N) ,但前者常數小一些,且實現較容易。
  • 內容: 後綴數組與名次數組
    • 後綴數組,SA[1~N],表示「排第幾的是誰?」。也就是將S的N個後綴升序排序,把排好序的後綴的開頭位置順次放入SA中。顯然,其知足:
      Suffix(SA[i])<Suffix(SA[i+1])
    • 名次數組,Rank[1~N],表示「你排第幾?」。也就是 Suffix(i) 在全部後綴中升序排序的名次。
  • 用途:
    • 最長公共前綴
    • 單個字符串的相關問題
      • 重複子串
        • 可重疊最長重複子串
        • 不可重疊最長重複子串 (pku1743)
        • 可重疊的最長重複子串 (pku3261)
      • 子串的個數
        • 不相同的子串的個數 (spoj694, spoj705)
      • 迴文子串
        • 最長迴文子串 (ural1297)
      • 連續重複子串
        • 連續重複子串 (pku2406)
        • 重複次數最多的連續重複子串 (spoj687, pku3693)
    • 兩個字符串的相關問題
      • 公共子串
        • 最長公共子串 (pku2774, ural1517)
      • 子串的個數
        • 長度不小於k的公共子串的個數 (pku3415)
    • 多個字符串的相關問題
      • 不小於k個字符串中的最長子串 (pku3294)
      • 每一個字符串至少出現兩次且不重疊的最長子串 (spoj220)
      • 出現或反轉後出如今每一個字符串中的最長子串(pku3294)

還有一種叫作後綴數組和後綴樹的,後綴樹是能夠轉發爲後綴數組的,這兩種構造起來很不簡單,可是複雜度倒是驚人的好。如求最長重複連續子串,出現次數最多的子串等都能用它完美的解決。有興趣的能夠搜搜,後綴數組的資料應該是比較多的,然後綴樹因爲太複雜,資料不是不少,仍是有的。

關於後綴數組構造的倍增算法,有一個特別好玩的小故事,你們能夠去看看~

《後綴樹,後綴數組,離散化》,去看73到81頁,可愛的小白兔們^_^

模糊匹配

上面介紹的都是精確匹配的算法,其實對於字符串,還有一種模糊匹配,有興趣的讀者能夠閱讀一本叫作《柔性字符串匹配》的書,確定會讓你獲益匪淺。

其餘

  • 後綴自動機
  • Manacher
相關文章
相關標籤/搜索