字串
課堂補充 by qazwsxedcrfvtg14
https://tinyurl.com/ybqbsr48Trie
• 假設你現在每個字元的大小都是65536(UTF-16)
• 你的Trie要怎麼建?
• 節省記憶體,每個節點換成一棵二元搜尋樹
• 時間複雜度O(NC+Q)->O(NlogC+QlogC)
• 空間複雜度O(NC)->O(N)
KMP
• Morris-Pratt Algorithm
• Knuth-Morris-Pratt Algorithm
• 差異只有 Failure Function
KMP
• MP
• -1 -1 -1 0 1 -1 0 1 2
• a b c a b d a b c
• KMP
• -1 -1 -1 -1 1 -1 -1 -1 X
• a b c a b d a b c
Gusfield Algorithm
• 又稱Z algorithm
• 字串S[0:N-1]的Z-value
• Z[i] = 最大的k滿足 S[0:k-1] = S[i:i+k-1]
• 拿 S從i開始的後綴 跟 S 比一比,最長的共同前綴長度
• Z[0]=0
i 0 1 2 3 4 5 6 7 8
S[i] a b a a b a a b b
Z[i] 0 0 1 5 0 1 2 0 0
觀察
• 算完Z[0]~Z[i-1]後,現在要計算Z[i],取任一個 b < i
• S[0:Z[b]-1] = S[b:b+Z[b]-1]
• 若b+Z[b] > i
• x = i-b
• S[x:Z[b]-1] = S[i:b+Z[b]-1]
0 x Z[b] b i b+Z[b]
觀察右界和i的關係
0 x Z[b] b i b+Z[b]
0 x Z[b] b i b+Z[b]
0 Z[b] x b b+Z[b] i
x+Z[x]
x+Z[x] i+Z[x]
實作
跟字串匹配沒關係啊
• ?
• 直接捏
• 把[短字串+(一個奇怪字元)+長字串]拿去求Z-value會怎樣呢?
Rolling hash
• 又稱 RK 算法(Robin-Karp Algorithm)
• 核心
Rolling hash
• 假設你有一個字串,且你已經知道其hash值
• 下列哪些操作可以O(1)執行?
• 加一個字元在前面
• 加一個字元在後面
• 從前面刪除一個字元
• 從後面刪除一個字元
Rolling hash
• 可以把Rolling hash想像成一個前高後低三角形
Rolling hash
• 兩個hash接起來
• 一個字元也可以 算是一個hash
*𝐶𝑏
Rolling hash
• 刪除前面的字元
*𝐶𝑏
Rolling hash
• 刪除後面的字元
*𝐶−𝑏 模逆元
Rolling hash
• 因為這些性質
• 我們經常會預處理好字串每個前綴的Rolling hash
Rolling hash
• 這樣之後就能直接算出任意一段的hash值
Suffix Array
• 現在給你一個字串,拿出他的所有後綴後,把那些後綴排序所得 到的結果就是Suffix Array
• 例子:
• 字串:abacab
• 後綴:abacab、bacab、acab、cab、ab、b
• 排序
• ab
• abacab
• acab
• b
• bacab
• cab
Suffix Array
• 怎麼做呢?
• 倍增法
Suffix Array
• a b a c a b a d
• 1 2 1 3 1 2 1 4
• a b a c a b a d
• 12 21 13 31 12 21 14 40
• a b a c a b a d
• 1 4 2 5 1 4 3 6
Suffix Array
• a b a c a b a d
• 1 4 2 5 1 4 3 6
• a b a c a b a d
• 12 45 21 54 13 46 30 60
• a b a c a b a d
• 1 5 3 7 2 6 4 8
Suffix Array
• a b a c a b a d
• 1 5 3 7 2 6 4 8
• a b a c a b a d
• 12 56 34 78 20 60 40 80
• a b a c a b a d
• 1 5 3 7 2 6 4 8
Suffix Array
• a b a c a b a d
• 1 5 3 7 2 6 4 8
• 時間複雜度O(NlogN)
• abacabad
• abad
• acabad
• ad
• bacabad
• bad
• cabad
• d
Suffix Array
• Longest Common Prefix
• 在SA中常被稱為H陣列
• 0 abacabad
• 3 abad
• 1 acabad
• 1 ad
• 0 bacabad
• 2 bad
• 0 cabad
• 0 d
Suffix Array
• Longest Common Prefix
• 你發現一個性質
• AAB和他前一個位置的BAAB之間的H有什麼關係
• H(AAB~)>=H(BAAB~)-1
• 因此你可以照著字串原本的順序直接做,每個H都從前個順序的 H-1開始算
• 仔細算一下,會發現這樣的時間複雜度是O(N)
跟字串匹配沒關係啊
• ?
• 直接捏
• 試著在Suffix Array上做二分搜,然後用H陣列O(1)比對
字串技能樹
KMP Z
Algorithm Suffix
Array Hash
AC自動機 後綴
自動機 回文
自動機 Trie
可持久化 NTT Treap
例題
• 假設兩個字串相似的定義如下
• 如果存在一個字元的置換方式,使得兩個字串相等,則這兩個字串相似
• 例:
• AAA=BBB
• XYX=ABA
• ABA!=AAA
• 問:給你字串A和字串B,A中有多少子字串和B相似?
• |A|,|B|<10^6
• 問:給你字串A和字串B,A中有多少子字串和B的子字串相似?
• |A|<10^6,|B|<10^3
例題
• 回文的定義:把順序倒過來還是一樣的字串
• 例:ABCCBD、ABCBA、QAQ
• 問:給定一個字串,請問裡面最長的回文長度是?
例題
• 給你字串A和字串B,現在有Q筆詢問
• 每個詢問會從A和B中各切一段下來,分別為C和D
• 問: D在C中出現幾次。