有限状态机
一个有限状态机(FSM) M 是一个 5-tuple,包括
Q: 有限的状态集合
q0: 初始状态
A: 可接受状态
SIGMA: 有限的输入字符
delta: 状态转移函数
用于字符串匹配的有限状态机的状态总数,其实和文本长度无关,只是模式字符串的长度而已,因为任意时候的当下状态,都是P的k个前缀匹配成功,k可以是1到m(即P的长度),当k为m时,也就是匹配成功了。
因此我们可以有一个最终状态函数 phi,来描述有限状态机器的当下状态,这个函数有如下的递归表达式
phi(epsilon) = q0 (epsilon 是空输入)
phi(wa) = delta(phi(w), a)
可见 phi 是依赖于状态转移函数 delta 的,那么 delta 的表达式是什么呢,书中也给出了
delta(q, a) = sigma(qa)
其中 sigma(x) 叫做后缀函数,借用前面的Python版后缀定义来表示一下,就是
sigma(x) = max{k: x.endswith(P[0:k])}
状态函数和后缀函数之间的联系在书中有严格的数学证明,但用白话说一下很好理解,就是状态机当前的状态,假设为 k 的话,就说明 P 的 k 个前缀匹配成功,k 可以是1到 m(即P的长度),当 k 为 m 时,也就是匹配成功了。
代码也比较直白,除了下标有点绕,所以建议和书对照看,但是注意书中第922页的代码有误.
def finite_automation_matcher(t, delta, m):
n = len(t)
q = 0
for i in range(0, n):
q = delta[(q, t[i])]
print "i %d, t[%d] %s, status %d"%(i, i, t[i], q)
if q == m:
print "Pattern occured with shift %d"%(i-m+1)
def compute_transition_function(p, SIGMA):
delta = {}
m = len(p)
for q in range(0,m+1):
for a in SIGMA:
k=min(m,q+1)
while not (p[0:q]+a).endswith(p[0:k]):
k=k-1
delta[(q,a)]=k
return delta
def test_fsm():
t = "abababacaba"
p = "ababaca"
m = len(p)
SIGMA = "abc"
delta = compute_transition_function(p, SIGMA)
finite_automation_matcher(t, delta, m)
最后可将结果跟书中Figure 32.7 对比一下