1 1 Lecture 11 模式匹配 清华大学 宋斌恒 2 内容介绍 ?解决问题:模式匹配,对应实际问题: –文本文件字符串查找 –格式文件中的字符串及其格式查找问题 ?算法:Na?ve,Rabin Karp, 自动机, KMP,BM算法 3 Figure 32.1 The string-matching problem. The goal is to find all occurrences of the pattern P = abaa in the text T = abcabaabcabac. The pattern occurs only once in the text, at shift s = 3. The shift s = 3 is said to be a valid shift. Each character of the pattern is connected by a vertical line to the matching character in the text, and all matched characters are shown in green color. text T pattern P b aaba a cabacbaabac 4 本章算法及其复杂度列表 Algorithm preprocessing time matching time Na?ve 0 O((n-m+1)m) Rabin-KarpΘ(m) O((n-m+1)m) Finite automaton O(m|Σ|)Θ(n) Knuth Morris Pratt O(m)Θ(n) BM 5 Terminology ? Σ: 字符集 ? Σ * :由Σ生成的所有字符串,包括空串的 集合,以下叙述x, y, z, w表示其元素 ? Concatenation of x,y:xy ?前缀:[: w [ x ?there exists y,such that x=wy ?后缀:] : w ]x ?there exists y,such that x=yw 6 Lemma 32.1 (Overlapping-suffix lemma) Suppose that x, y, and z are strings such that x ] z and y ] z. If |x| ≤|y|, then x] y. If |x| ≥|y|, then y ] x. If |x| = |y|, then x = y. 2 7 Figure 32.3 A graphical proof of Lemma 32.1. We suppose that x ] a and y ] z. The three parts of the figure illustrate the three cases of the lemma. Vertical lines connect matching regions (shown shaded) of the strings. (a) If |x| ≤|y|, then x ] y. (b)If |x| ≥|y|, then y ] x. (c) If |x| = |y|, then x = y. 8 Na?ve String matching algorithm ? Na?ve-String-matcher(T,P) 1. n?length[T] 2. m?length[P] 3. For s ?0 to n-m 1. If P[1,…,m]==T[s+1,…,s+m] 1. Print “Pattern occurs with shift” s 9 Rabin Karp algorithm ? Hash Value p of a string P with modulo q: – p=hash(P,m,q)=(P[m]|Σ| 0 + P[m-1]|Σ| 1 + P[m-2]|Σ| 2 +…+ P[m-i]|Σ| i +…+ P[1]|Σ| m-1 ) mod(q) –计算方法:多项式求值方法, ?算法描述: –给定字符串T和要找的子字符串P, –从i=1到Length[T]-Length[P] ? If Hash(P,m,q)!=Hash(T[i,m],m,q) continue ?继续判断(na?ve方法) ?其中T[i,m]表示T从i开始长度为m的子串 10 Key Points of Karp-Rabin ? How to compute the value efficiently? –t s+1 = Hash(T[s+1,m],m,q) –t s+1 =(d(t s -T[s+1]h)+T[s+m+1]) mod(q) –h=d m-1 (mod q) –d是进位,如果是26个字符,则可以是26, 一般来讲取d为|Σ| ? Spurious Hit 11 2 76251413209 7 53 3 9 9 2 1 12 2 76251413209 7 53 3 9 9 2 1 81 4 5 10 110 7 9 1111398 3 13 3 25141 87 14152≡(31415-3·10000) · 10+2(mod 13) ≡(7-3 · 3) · 10+2(mod 13) ≡8(mod 13) 14 ? Rabin-Karp-Matcher(T,P,d,q) 1. n=length[T] 2. m=length[P] 3. h=d m-1 (mod q) 4. p=0 5. T 0 =0 6. For i =1 to m 1. p=(dp+P[i]) (mod q) 2. t 0 =(dt 0 +T[i]) (mod q) 7. For s = 0 to n-m 1. If p=t s 1. If P[1,…,m]=T[s,…,m+s], print “pattern occurs at ” s 2. If s<n-m 1. t s+1 =(d(t s -T[s+1]h)+T[s+m+1] mod(q) 15 String matching with finite automata ?有限自动机M:5-tuple (Q,q 0 ,A,Σ,δ) ? Q is a finite set of states ?q 0 in Q is the start state ? A contains in Q is a distinguished set of accepting states ? Σ is a finite input alphabet ? δ is a function from Q×Σ into Q called the transition function of M 16 有限自动机示例: 0 1 001 010 bastate input ?δ ?Σ 1A ?q 0 ?Q abaaa accepted abbbaaa accepted abbaa rejected 17 Final-state function ? φ: Σ ? ?Q ? φ(ε)=q 0 ? φ(wa)=δ(φ(w),a) for w in Σ ? , ainΣ 18 String matching automata ? Given pattern P, to construct an automaton: ?M= (Q,q 0 ,A,Σ,δ) where ? Σ = the alphabet in P ? Q = {0,1,2,…,m: integer s means the current state has exactly s characters match the pattern}, m=length[P] ?q 0 =0 ?A={m} ? δ : δ(q,a)=σ(P q a), σ(x)=max{k:P k =x}, P k 表示P 的前k个字符,称为后缀函数。【研究!】 4 19 Automaton for “ababaca” 0 1 2 3 4 5 6 7 其它转移如何做?其它转移如何做? 转移函数?转移函数? 20 0 2 3 4 5 61 7 21 1 00 1 02 3 00 1 04 5 00 1 64 7 00 1 02 22 自动机工作的一个例子 i — 1 2 3 4 5 6 7 8 9 10 11 T[i] — a b a b a b a c a b a stateφ(T i ) 0 1 2 3 4 5 4 5 6 7 2 3 23 算法描述: ? Finite-Automaton-Matcher(T,δ,m) 1. n=length[T] 2. q=0 3. For i = 1 to n 1. q=δ(q,T[i]) 2. If q==m then print “pattern occurs at” i-m 24 后缀函数σ的属性: 【引/定理32.2/3/4】 ? σ(xa)≤σ(x)+1 ? If q= σ(x) then σ(xa)=σ(P q a) ?如果φ是模式P决定的自动机的最终状态 函数,则φ(T i )=σ(T i ) 5 25 Figure 32.8 An illustration for the proof of Lemma 32.2. The figure shows that r ≤σ(x) + 1, where r =σ(xa). 1?r p r p 26 Figure 32.9 An illustration for the proof of Lemma 32.3. The figure shows that r =σ(P q a), where q = σ(x) and r =σ(xa). q p r p 27 COMPUTE-TRANSITION-FUNCTION(P, ∑) 1m←length[P] 2for q←0 to m 3 do for each character a∈∑ 4 do k←min(m + 1, q + 2) 5 repeat k←k-1 6 until P k ] P q a【是后缀!】 7δ(q, a)←k 8 return δ 28 Knuth-Morris-Pratt Algorithm ?中心思想:克服na?ve 算法和有限自动机 算法的重复工作! ?主要步骤:计算辅助函数π[1,2,…,m]它只 与Pattern相关,用来说明Pattern的重复情 况。 29 a aaba b bcbaabababc ba acb 在某S处开始有5个字符匹配,第六个不匹配, 这时找一个短一些的匹配串:即从第S+2处开 始的长度为3的地方匹配,见下页 30 a aaba b bcbaabababc ba acb 6 31 aba ababa q P k P 32 21 109876543 ba acbababa 00 10654321 33 ba bababa ba baba ba ba ba 8 P 6 P 4 P 2 P 0 P c a a b c a π[8]=6 a b a b c a π[6]=4 a b a b a b c a π[4]=2 a b a b a b a b c a π[2]=0 ε 34 KMP-MATCHER(T, P) 1n←length[T] 2m←length[P] 3π←COMPUTE-PREFIX-FUNCTION(P) 4q←0 Number of characters matched. 5for i←1 to n Scan the text from left to right. 6 do while q > 0 and P[q + 1] ≠T[i] 7do q←π[q] Next character does not match. 8ifP[q + 1] = T[i] 9 then q←q + 1 Next character matches. 10 if q = m Is all of P matched? 11 then print “Pattern occurs with shift” i-m 12 q←π[q] Look for the next match.       35 COMPUTE-PREFIX-FUNCTION(P) 1m←length[P] 2π[1] ←0 3k←0 4for q←2 to m 5 do while k > 0 and P[k + 1] ≠P[q] 6 do k←π[k] 7if P[k +1] = P[q] 8 then k←k +1 9 π[q] ←k 10 return π 36 BM算法 ? The Boyer-Moore algorithm ?一种从右边开始进行匹配的算 法 7 37 主要思想 从右向左比: 当目标串中的字符根本就没有在模式串中出现,模 式串就可以从这一字符开始向右移动m位置数。 例子:位置0 1 2 3 4 5 6 7 8 9 … 目标串a b b a d a b a c b a 模式串b a b a c b a b a c 这种算法最好的情况就是模式串每一次和目标串比 较,它们第一个字符就不匹配,且目标串中的字符不 在模式串中出现,这样模式串每一次都可移动m位。 38 坏字符试探 Bad character heuristics 目标串和模式串第一个字符不匹配, 且目标串的第一个字符在模式串的其它 位置出现,在这种情况下,模式串右移 到其相应字符与目标串第一个字符匹配 的位置上。 39 示例 位置0 1 2 3 4 5 6 7 8 9 … 目标串a b b a b a b a c b a 模式串b a b a c b a b a c b-c导致不匹配,但目标串字符b出现在模 式串的位置0和位置2,于是模式串可右移2 位,使其最右边的字符b和目标串的第一个字 符b匹配。 40 Good suffix heuristics 位置0 1 2 3 4 5 6 7 8 9 … 目标串a b a a b a b a c b a 模式串c a b a b c a b a b √ 目标串和模式串的后缀ab已匹配,模 式串应当右移2位,使其从右至左的第二 个子串ab与目标串的后缀ab匹配。 41 Good suffix heuristics 下面这个例子中,同样目标串和模式 串的后缀ab已匹配,但子串ab没有在模 式串的其它位置出现。所以模式串可以 右移5位。 位置0 1 2 3 4 5 6 7 8 9 … 目标串a b c a b a b a c b a 模式串c b a a b c b a a b 42 Good suffix heuristics 目标串和模式串的后缀bab已匹配,在位置 1出现a-b不匹配,同时子串bab也没有再出现在 模式串中,但在这种情形下模式串不能象上一 种情形右移5位,而只能右移3位,因为模式串 的前缀ab和子串bab(也就是目标串的子串 bab)的后缀匹配。 位置0 1 2 3 4 5 6 7 8 9 … 目标串a a b a b a b a c b a 模式串a b b a b a b b a b 8 43 对“坏字符”情况的预处理 对于这种情况,我们首先定义一个函数occ 生成一个数组,在这个数组中记录广义字母表 的每一个字符在模式串中出现的最右边的位 置,如果根本没有出现在模式串中,则记-1。 定义: 其中p 0 p 1 …p m-1 代表模式串,a是广义字母 表中的任一字符。 a1- aa} = p | j max{ = a) occ(p, j ? ? ? ? ? 没有在模式串中出现如果 出现在模式串中如果 44 算法: bmInitocc() for a ←0 to alphabetsize do occ[a] ←-1 for j ←0 to m do a ←p[j] occ[a] ←j 例子: occ(text, x) = 2 occ(text, t) = 3 45 对“好后缀”情况的预处理 我们也要建立一个数组s。数组里的 第i项代表不匹配发生在模式串的位置i-1 (即模式串位置i开始的后缀已和目标串 相应子串匹配)时模式串应当右移的位 数。 然后再建立一个数组f。第i项代表模 式串中从位置i开始的后缀其最长边界开 始的位置。 46 对“好后缀”情况的预处理 第一种情形:已匹配的后缀子串在模式串的 其它位置又出现。 i: 0 1 2 3 4 5 6 7 p: a b b a b a b f: 5 6 4 5 6 7 7 8 s: 0 0 0 0 2 0 4 1 47 对“好后缀”情况的预处理 第二种情形:已匹配的后缀子串仅仅有一部 分又出现在模式串的开头。 例子:i: 0 1 2 3 4 5 6 7 p: a b b a b a b f: 5 6 4 5 6 7 7 8 s: 5 5 5 5 2 5 4 1 48 bmPreprocess1() i ←m j ←m+1 f[i] ←j while i>0 do while j<=m and p[i-1]≠p[j-1] do if s[j]=0 then s[j] ←j-1 j ←f[j] i ←i-1 j ←j-1 f[i]=j bmPreprocess2() j ←f[0] for i ←0 to m do if s[i]=0 then s[i] ←j if i=j then j ←f[j] BM预处理算法 bmPreprocess() call bmInitocc() call bmPreprocess1() call bmPreprocess2() BM检索算法 bmSearch() i ←0 while i<=n-m do j ←m-1 while j>=0 and p[j]==t[I+j] do j ←j-1 if j<0 then return i i ←i+s[0] else i ←i+max(s[j+1],j- occ[t[i+j]]) 9 49 总结 BM算法也将匹配过程分为了对模式串的预 处理阶段(preprocessing),和检索(Searching)阶 段。 一般情况下,算法的时间复杂度是O (n)。 在可选的字符数量远远大于模式串的长度 时,由于这将通常导致“坏字符”情况,模式串 一次即可右移m个位置,因此算法的时间复杂 度平均可以达到O (n/m)。