问了 30 个技术群,也问了无数的前辈,真是各种不礼貌,吃了无数闭门羹,还是自己看着有点眉目了
还有 wiki 的伪代码看了总觉得奇怪,于是看了同一页面其他语言翻译过来的伪代码,
发现葡萄牙语和俄罗斯语那里的 if 判断都还缺少一个条件
国内的资料比较少,这几份学习资料不错,比我稀里糊涂的思路要好,分享下:
http://www.liafa.univ-paris-diderot.fr/~carton/Enseignement/Complexite/
ENS/Redaction/2008-2009/yingjie.xu.pdf
http://www8.cs.umu.se/kurser/TDBC92/VT06/final/1.pdf
http://arxiv.org/pdf/1010.5318.pdf
对于一个确定型自动机 D = (Q, Σ, δ, q0, F),Q 的一系列恒等关系 ρi (i ≥ 0) 被定义为:
ρ0 = {(p, q)|p, q ∈ F} ∪ {(p, q)|p, q ∈ Q ? F},
ρi+1 = {(p, q) ∈ ρi|(?a ∈ Σ)(δ(p, a), δ(q, a)) ∈ ρi}.
ρi有如下关系:
ρ0 ? ρ1 ? · · · .
若 ρi = ρi+1 则对于 ρi = ρj (j > i).
存在 0 ≤ k ≤ |Q| 满足 ρk = ρk+1.
对于 ρi ≠ ρi+1,存在以下性质Equation 1:
ρi ≠ ρi+1 ? (?p, q ∈ Q, a ∈ Σ) (p, q) ∈ ρi and (δ(p, a), δ(q, a)) ? ρi
? (?U ∈ Q/ρi , a ∈ Σ) p, q ∈ U and (δ(p, a), δ(q, a)) ? ρi
? (?U, V ∈ Q/ρi , a ∈ Σ) p, q ∈ U and δ(p, a) ∈ V and δ(q, a) ? V
? (?U, V ∈ Q/ρi , a ∈ Σ) δ(U, a) ∩ V ≠ ? and δ(U, a) ? V
算法抽象:
1: Q/θ ← {F, Q ? F}
2: while (?U, V ∈ Q/θ, a ∈ Σ) s.t. Equation 1 holds do
3: Q/θ ← (Q/θ ? {U}) ∪ {U ∩ δ^-1(V, a), U ? U ∩ δ^-1(V, a)}
4: end while
算法细化:
1:W ← {F, Q ? F} # 有些版本上只是 W ← {F }
2: P ← {F, Q ? F}
3: while W is not empty do
4: select and remove S from W
5: for all a ∈ Σ do
6: la ← δ^-1(S, a)
7: for all R in P such that R ∩ la ≠ ? and R ? la do
8: partition R into R1 and R2: R1 ← R ∩ la and R2 ← R ? R1
9: replace R in P with R1 and R2
10: if R ∈ W then
11: replace R in W with R1 and R2
12: else
13: if |R1| ≤ |R2| then
14: add R1 to W
15: else
16: add R2 to W
17: end if
18: end if
19: end for
20: end for
21: end while
复杂度:
O(n log n)
还有一个优化的代码:
1: P = {F, Q ? F}
2: for all a ∈ A do
3: Add((min(F, Q ? F), a), S)
4: while S ≠ ? do
5: get (C, a) from S (we extract (C, a) according to the
strategy associated with S: FIFO/LIFO/...)
6: for each B ∈ P split by (C, a) do
7: B′, B′′ are the sets resulting from splitting of B w.r.t. (C, a)
8: Replace B in P with both B′ and B′′
9: for all b ∈ A do
10: if (B, b) ∈ S then
11: Replace (B, b) by (B′, b) and (B′′, b) in S
12: else
13: Add((min(B′,B′′), b), S)
找出无用状态:
state_graph1 = { 'total_states': [ 'A', 'B', 'C', 'D', 'E' ], 'initial_states': [ 'A' ], 'termination_states': [ 'D' ], 'state_transition_map': { 'A': { 'a': 'B', 'b': 'C' }, 'B': { 'a': 'B', 'b': 'D' }, 'C': { 'a': 'B' }, 'E': { 'a': 'E', 'b': 'E', }, 'D': { 'a': 'B' }, }, 'cins': [ 'a', 'b' ], } def get_unreachable_states( G ): reachable_states = set( G['initial_states'] ) new_states = set( G['initial_states'] ) total_states = set( G['total_states'] ) cins = G['cins'] state_transition_map = G['state_transition_map'] while True: temp_set = set() for state in new_states: for char in cins: try: next_state = state_transition_map[state][char] temp_set.update( next_state ) except KeyError: pass new_states = temp_set - reachable_states reachable_states.update( temp_set ) if new_states == set(): break unreachable_states = total_states - reachable_states return unreachable_states print get_unreachable_states( state_graph1 )
Hopcroft:
import random from copy import deepcopy state_graph1 = { 'total_states': [ '1', '2', '3', '4', '5', '6', '7' ], 'initial_states': [ '1' ], 'termination_states': [ '6', '7' ], 'state_transition_map': { '1': { 'a': '3', 'b': '2' }, '2': { 'a': '4', 'b': '2' }, '3': { 'c': '3', 'b': '6', 'd': '5' }, '4': { 'b': '7', 'd': '5', 'c': '3' }, '5': { 'a': '4' }, '6': { 'b': '6' }, '7': { 'b': '6' }, }, 'cins': [ 'a', 'b', 'c', 'd' ], } state_graph2 = { 'total_states': [ 'A', 'B', 'C', 'D', 'E', 'F', 'S' ], 'initial_states': [ 'A' ], 'termination_states': [ 'C', 'D', 'E', 'F' ], 'state_transition_map': { 'S': { 'a': 'A', 'b': 'B' }, 'A': { 'a': 'C', 'b': 'B' }, 'B': { 'a': 'A', 'b': 'D' }, 'C': { 'a': 'C', 'b': 'E' }, 'D': { 'a': 'F', 'b': 'D' }, 'E': { 'a': 'F', 'b': 'D' }, 'F': { 'a': 'C', 'b': 'E' }, }, 'cins': [ 'a', 'b' ], } state_graph3 = { 'total_states': [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' ], 'initial_states': [ 'A' ], 'termination_states': [ 'C' ], 'state_transition_map': { 'A': { '0': 'B', '1': 'F' }, 'B': { '0': 'G', '1': 'C' }, 'C': { '0': 'A', '1': 'C' }, 'D': { '0': 'C', '1': 'G' }, 'E': { '0': 'H', '1': 'F' }, 'F': { '0': 'C', '1': 'G' }, 'G': { '0': 'G', '1': 'E' }, 'H': { '0': 'G', '1': 'C' } }, 'cins': [ '0', '1' ], } def hopcroft_algorithm( G ): cins = set( G['cins'] ) termination_states = set( G['termination_states'] ) total_states = set( G['total_states'] ) state_transition_map = G['state_transition_map'] not_termination_states = total_states - termination_states def get_source_set( target_set, char ): source_set = set() for state in total_states: try: if state_transition_map[state][char] in target_set: source_set.update( state ) except KeyError: pass return source_set P = [ termination_states, not_termination_states ] W = [ termination_states, not_termination_states ] while W: A = random.choice( W ) W.remove( A ) for char in cins: X = get_source_set( A, char ) P_temp = [] for Y in P: S = X & Y S1 = Y - X if len( S ) and len( S1 ): P_temp.append( S ) P_temp.append( S1 ) if Y in W: W.remove( Y ) W.append( S ) W.append( S1 ) else: if len( S ) <= len( S1 ): W.append( S ) else: W.append( S1 ) else: P_temp.append( Y ) P = deepcopy( P_temp ) return P print hopcroft_algorithm( state_graph1 ) print hopcroft_algorithm( state_graph2 ) print hopcroft_algorithm( state_graph3 )
岛津义弘:
“真田幸村,这片 ‘ 战国 ’ 的土地上有太多的冷漠和争斗,
一个人想要在这样的 ‘ 乱世 ’ 中心存温柔,他前进的道路定然会很痛苦,
但是最后能走到 ‘ 武 ’ 之巅峰的人,却往往又都是那样内心温柔的人。
因为这份温柔能够让人变得很强壮。
希望你即便面对的是你的敌人,挥舞自己的 ‘ 双枪 ’ 时,也不要失去这份温柔。”