字串
課堂補充 by qazwsxedcrfvtg14
補充 by boook
Hamming distance
漢明距離 漢明距離
• 兩個等長字符串對應位置的不同字符的個數。
• 例如:
• 1011101 與
• 1001001 之間的漢明距離是 2 。
• 2143896 與
• 2233796 之間的漢明距離是 3 。
• "toned" 與
• "roses" 之間的漢明距離是 3 。
例題 - codeforces 903E 例題 - codeforces 903E
• 現在有一個母字串 p 長度為 N ,現在要使用母字串 製造出 k 個小孩字串,製造方法:
• 1. 複製出一份獨立的母字串 P
• 2. 從裡面挑出兩個 index i, j
• 3. swap(pi, pj)
• 現在給你這 K 個小孩字串,請找到隨便一個母字串。
• K <= 2500, N <= 5000, K * N <= 5000
• 小寫字母
例題 - codeforces 903E 例題 - codeforces 903E
• 每一個母字串和小孩字串的漢明距離都很小
• K * N <= 5000, N <= 5000
• O(NNK)
• 可以枚舉可能的母字串, O(K) 判斷是否符合:
• 小孩字串的結構都要一樣
• 漢明距離 = 0 -> 有字元出現兩次
• 漢明距離 = 2
Z-value
Gus eld Algorithm fi Gus eld Algorithm fi
• 又稱 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 Z[b] b i b+Z[b
]
x
觀察右界和 i 的關係 觀察右界和 i 的關係
0 Z[b] b i b+Z[b
] x
0 Z[b] b i b+Z[b
] x
0 Z[b] b b+Z[b i
] x
x+Z[x]
x+Z[x] i+Z[x]
實作 實作
實作 實作
跟字串匹配沒關係啊 跟字串匹配沒關係啊
• ?
• 直接捏
• 把 [ 短字串 +( 一個奇怪字元 )+ 長字串 ] 拿去求 Z-value 會怎樣呢?
複雜度分析 複雜度分析
• O(N)?
Hash
Rolling hash Rolling hash
• 又稱 RK 算法 (Robin-Karp Algorithm)
• 核心
Rolling hash - 如果 C = 10 Rolling hash - 如果 C = 10
• S = 21334531
• M = 10000000000000000000000000000000000000000000
• H(1) = 2
• H(2) = 21
• H(3) = 213
• H(4) = 2133
• H(5) = 21334
• H(6) = 213345
• H(7) = 2133453
• H(8) = 21334531
Rolling hash Rolling hash
• 假設你有一個字串,且你已經知道其 hash 值
• 下列哪些操作可以 O(1) 執行 ?
• 加一個字元在前面
• 加一個字元在後面
• 從前面刪除一個字元
• 從後面刪除一個字元
Rolling hash Rolling hash
• 可以把 Rolling hash 想像成一個前高後低三角形
• H(1) = 2
• H(2) = 21
• H(3) = 213
• H(4) = 2133
• H(5) = 21334
Rolling hash Rolling hash
• 兩個 hash 接起來
• 一個字元也可以 算是一個 hash
*
• S = 213
• P = 123
• H(S) = 213
• H(P) = 123
• H(S+P)
= 213 * 1000 + 123
Rolling hash Rolling hash
• 刪除前面的字元
*
• S = 12345
• H(S) = 12345
• 12345 – 12000
= 345
Rolling hash Rolling hash
• 刪除後面的字元
*
• S = 12345
• H(S) = 12345
• (12345 – 45) / 100 = 123
• 8 / 2 != 2 / 2 (mod 6)
Rolling hash Rolling hash
• 因為這些性質
• 我們經常會預處理好字串每個前綴的 Rolling hash
Rolling hash Rolling hash
• 這樣之後就能直接算出任意一段的 hash 值
• S = 21334
• H(1) = 2
• H(2) = 21
• H(3) = 213
• H(4) = 2133
• H(5) = 21334
• H(3~4)
= H(4) – H(2) * 100 = 33
例題 - 怎麼訂 hash 值 例題 - 怎麼訂 hash 值
• 給一個矩陣大小為 N * N
• Q 次詢問兩個大小相同的子矩陣是否相同。
• N <= 5000
• Q <= 500000
• hash 可不可以推廣到二維?
二維 hash
二維 hash
例題 - zerojudge c706 例題 - zerojudge c706
HASH 的安全性 ?
• 給定 hash function 中的 C 和 M(mod)
• C = 131
• Mod = 9007199254740992
• 請找到兩個 hash value 相同的字串,長度小於 30 ?
生日悖論 生日悖論
• 一個房間要多少人,則兩個人的生日相同的機率大於 50%?
• 23 人
• 有
n
個人,每人都隨機地從N
個特定的數中選擇出來一個數。
•
p
(n
) = 有兩個人選擇了同樣的數字。• 這個機率有多大 ?
例題 – 怎麼訂 hash 值 例題 – 怎麼訂 hash 值
• 假設兩個字串相似的定義如下
• 如果存在一個字元的置換方式,使得兩個字串相等,則這兩個字串相似
• 例 :
• AAA=BBB
• XYX=ABA
• ABA!=AAA
• 問 1: 給你字串集 A 和字串 B , A 中有多少字串和 B 相似
?
• 問 2: 給你一個字串 C , Q 次問兩段區間是否相似 ?
• Sum(|Ai|), |A|, |B| < 10^6, C, Q <= 10^6
Suffix array
Suffix Array Suffix Array
• 現在給你一個字串,拿出他的所有後綴後,把那些後綴排序所得 到的結果就是 Suffix Array
• 例子 :
• 字串 :abacab
• 後綴 :abacab 、 bacab 、 acab 、 cab 、 ab 、 b
• 排序
• ab
• abacab
• acab
• b
• bacab
• cab
Suffix Array Suffix Array
• 怎麼做呢 ?
• 倍增法
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 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 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 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 Suffix Array
• Longest Common Pre xfi
• 在 SA 中常被稱為 H 陣列
• Height 陣列
• 0 abacabad
• 3 abad
• 1 acabad
• 1 ad
• 0 bacabad
• 2 bad
• 0 cabad
• 0 d
Suffix Array Suffix Array
• Longest Common Pre xfi
• 你發現一個性質
• 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
Manacher
回文算法
例題 例題
• 給你字串 A 和字串 B ,現在有 Q 筆詢問
• 每個詢問會從 A 和 B 中各切一段下來,分別為 C 和 D
• 問 : D 在 C 中出現幾次。
例題 例題
• 給一個字串 S ,求最長的 XX 子字串的長度。
• 弱化 by codeforces 319D
• 例子:
• 123abcabc456 -> abcabc
• aabbcc -> aa || bb || cc
• aaaaaa -> aaaaaa
• Len(s) <= 10^5