上一篇:字符串匹配(string matching)算法之一 (Naive and Rabin_Karp)
有限自动机:
一个有限自动机M是一个5元组(Q, q0, A, Σ, δ), 其中:
· Q是状态的有限集合
· q0 ∈ Q 初始状态
· A ⊆ Q 是一个接受状态的集合
· Σ 有限的输入字母表
· δ 是从Q × Σ 到Q的函数, 称为M的转移函数(transition function )
有限自动机开始于状态q0,每次读入输入字符串的一个字符.
如果在状态q时读入输入字符a,则它从状态q变为δ(q, a).
当其当前状态q属于(接受状态的集合)A时, 则说自动机M接受了迄今为止所读入的字符串.
没有被接受的输入称为被拒绝的输入.
有限自动机M可以推导出一个函数φ, 称为终态函数。φ(w)是M在扫描字符串w后终止时的状态。
φ(ε) |
= |
q0, |
φ(wa) |
= |
δ(φ(w), a) for w ∈ Σ*, a ∈ Σ. |
因此, M接受字符串w当且仅当φ(w) ∈ A
字符串匹配自动机
给定模式P[1 ‥ m], 定义辅助函数σ数相应P的后缀函数.
函数σ是一个从Σ*到{0, 1, . . . , m}上的映射:
σ(x)是x的后缀且是p的最长前缀的长度.
σ(x) is the length of the longest prefix of P that is a suffix of x:
σ(x) = max {k : Pk ⊐ x}.
例如模式P = ab, σ(ccaca) = 1, and σ(ccab) = 2
对一个长度为m的模式P来说, σ(x) = m 当且仅当 P ⊐ x (P是x的后缀).
给定模式P[1..m], 其对应的字符串匹配自动机的定义如下:
l 状态集Q为{0, 1, …, m}, 初始状态q0, 状态m是唯一的接受状态.
l 对任意的状态q和字符a, 变迁函数δ的定义为: δ(q, a) = σ(Pqa). (其中Pq是P的前缀P[1..q])
也就是把状态q设为当前已匹配的长度.
例如模式P=ababaca. 文本T=abababacaba.
有δ(5, b) = 4, 如果从状态q=5时自动机读入一个b, 则Pqb=ababab, 于是ababab的后缀匹配P的最长前缀为P4 = abab.
(The longest prefix of P that is also a suffix of ababab is P4 = abab)
//字符串匹配自动机
FINITE-AUTOMATON-MATCHER(T, δ, m)
1 n ← length[T]
2 q ← 0
3 for i ← 1 to n
4 do q ← δ(q, T[i]) //δ函数其实是一张表,预先计算出所有值,需要时查询
5 if q = m
6 then print "Pattern occurs with shift" i – m
匹配时间复杂度Θ(n).
//下面计算出δ函数
COMPUTE-TRANSITION-FUNCTION(P, Σ)
1 m ← length[P]
2 for 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 Pk ⊐ Pqa
7 δ(q, a) ← k
8 return δ
时间复杂度O(m3 |Σ|)..还存在更快的过程。
附录:
用Σ* 表示用字母表Σ中的所有有限长度的字符串的集合
长度为0的空字符串用ε表示,ε也属于Σ*
字符串前缀 后缀
如果某个字符串 y ∈ Σ*,使得x=wy ,则称w是x的前缀, 记为w ⊏ x 。 如果w是x的后缀,记为w ⊐ x
《Introduction to Algorithms》- CLRS