看了一下網上的方法基本上是使用「集合的分割」實現的極小化,剛好我們老師使用的是矩陣掃瞄,因此自己乾脆使用j**a來實現。我直接封裝了乙個dfa的類,目前只寫了「矩陣掃瞄」的極小化,有時間的話自己也會把「集合分割」的演算法加上。下面就拿網上找到的例子做乙個使用矩陣掃瞄的基本步驟。
關鍵步驟:
去除無用狀態
合併等價狀態
例子:第一步:
畫乙個矩陣,可以是下面這樣的。因為(a,c)和(c,a)一樣,也就是說這是乙個對角陣,所以只需要使用下三角(上三角)即可:
第二步去除對角線,以-1作為去除的標記
第三步終態和非終態是不能合併的,因此需要把終態和非終態去掉。由dfa知道,非終態集為,終態集為,在下三角中把(e,a),(e,b),(e,c),(e,d)去掉。這一步我使用1做為標記,因為在j**a裡面int型預設為0,所以這樣做可以避免初始化的時候賦值。
注意:在程式中除了對角線使用-1,其餘我都使用1和0作為標記,1表示不可合併,0為可合併。
下面是去掉後的結果:
第四步開始做下三角的掃瞄,只需要掃瞄空白(程式中標記為0)的地方即可,當然在程式中迴圈掃瞄的時候,還是需要遍歷下三角的。
第一遍:
b,af(b,a) = b f(a,a) = b (解釋:這既是跳轉函式,b輸入a跳到b狀態,a輸入a也跳轉到b狀態。因為b和b是同乙個狀態,所以保留b,a)
f(b,b) = d f(a,b) = c (d,c狀態未知,保留)
c,af(c,a) = b f(a,a) = b
f(c,b) = c f(a,b) = c
c,bf(c,a) = b f(b,a) = b
f(c,b) = c f(b,b) = d
d,af(d,a) = b f(a,a) = b
f(d,b) = e f(a,b) = c (解釋:(e,c)已經被標記上1,所以(d,a)也要被標記為1)
d,bf(d,a) = b f(b,a) = b
f(d,b) = e f(b,b) = d (同(d,a))
d,cf(d,a) = b f(c,a) = b
f(d,b) = e f(c,b) = c
第一遍掃瞄後的結果如下:
注意:因為在上一次的基礎上,下三角的狀態已經發生了變化,所以需要進行第二次掃瞄。如果第二次又發生變化,那麼就需要第三次掃瞄。直至狀態不在改變,這時候就是最小化的最終結果。
第二遍:
b,af(b,a) = b f(a,a) = b
f(b,b) = d f(a,b) = c (因為(d,c) == 1,所以(b,a) = 1)
c,af(c,a) = b f(a,a) = b
f(c,b) = c f(a,b) = c
c,bf(c,a) = b f(b,a) = b
f(c,b) = c f(b,b) = d
本次掃瞄結果:
下三角狀態發生改變,進行第三遍掃瞄:
第三遍:
c,af(c,a) = b f(a,a) = b
f(c,b) = c f(a,b) = c
這一遍後,下三角的狀態沒有發生改變,不需要在進行第四遍掃瞄。這說明掃瞄已經結束了,而最終結果便是上一次掃瞄的結果:
從圖中可以看出,(c,a)處留空,說明a,c是可合併的狀態,其他狀態不可以合併
**結果:**可合併的狀態為
需要說明的是,掃瞄的步驟中,我每一步的跳轉都寫出來了,這只是為了更好的理解和闡述,同時說明了在程式中實現的過程。但是在實際的手動掃瞄時,很多重複的步驟是可以省略的。
/**
* 採用矩陣掃瞄法
* @return 成功:下三角矩陣,失敗:null
*/public
int[
]matrixscan()
//去掉終態
for(
int i =
1; i < matrix.length; i++)}
else}}
// 最後的掃瞄
// 區域性內部類
class
scanmatrix
// 注意max和min不應該相等
// 既不能是對角線上的1
if(matrix[max]
[min]==1
&& max != min)}}
}}}}
}new
scanmatrix()
.scan()
;return matrix;
}
測試資料:
a:0,b:0,c:0,d:0,e:1
a,bb,c,b,d,b,c,b,e,b,c
結果:
點選跳轉
執行結果肯定是和分析的結果一樣,但是在編寫的時候難免會有疏漏的地方,敬請指正!
Hopcroft最小化演算法化簡DFA
我們將乙個正規表示式通過myt演算法轉化成了乙個不確定有限自動機 nfa 又千辛萬苦用子集構造演算法整合掉多餘的狀態,生成了乙個確定有限自動機 dfa 然後發現狀態還是太多了,並不是最精簡的 狀態最少的。為了讓計算機更快地執行,只好我們再出馬給他整乙個演算法,來化簡dfa,直到狀態數最少。這個演算法...
面試演算法題 尋找矩陣的極小值
給定乙個 n n 的矩陣,矩陣中包含 n n 個 互不相同 的整數。定義極小值 如果乙個數的值比與它相鄰的所有數字的值都小,則這個數值就被稱為極小值。乙個數的相鄰數字是指其上下左右四個方向相鄰的四個數字,另外注意,處於邊界或角落的數的相鄰數字可能少於四個。要求在 o nlogn 的時間複雜度之內找出...
NMF演算法 非負矩陣分解演算法 python實現
nmf演算法 非負矩陣分解演算法。目標 將乙個大矩陣分解成兩個稍小的矩陣 利用矩陣的乘法 要求 待分解矩陣不能有負值。因為負值對於資料是無效的。假定有乙個元資料矩陣v,目標是將其分解成兩個非負矩陣w和h相乘的形式。v w h 這邊需要注意一些維度也就是角標,我就會直接寫了 其中,w稱為權重係數矩陣,...