有窮自動機

ADFA的可判定性

Problem description

ADFA={< B,w >|B是DFA,w是串,B接收w}證明:ADFA是可判定的。 實驗方法:編寫一個算法/程序,對於任意給定的輸入<B,W>,可以判定ADFA。 

Input

有多個測試序列,測試結束於測試文件結束;每個測試序列的第一行爲幾個正整數n m t a分別表示有n個狀態,從a開始m個小寫字母組成的字符集,第一個狀態默認爲起始狀態。t個接受狀態和a個測試串,接下來爲一個n行m列的矩陣S,其中S[i][j]表示第i行第j列,意義爲狀態i經過字母j到達狀態S[i][j]。接下來有t個數字,表示t個接受狀態值,然後是a行,每行一個串表示待測試的串。

Output

對於每個字符串輸出YES表示該DFA接受該串,NO表示不接受。

Sample Input

3 3 1 2

2 3 2

3 3 3

3 3 3

2

a

b

Sample Output

YES

NO

 

對於這個問題,我們需要知道DFA是什麼,以及它的運行原理是怎樣的。

 

 

DFA及其原理


有窮自動機例子:

 

 


那麼M1識別正則語言A={w|w至少含有一個1並且在最後的1後面有偶數個0}

 

 

那麼DFA是什麼呢?對,DFA是確定型的有窮自動機,意思就是當機器處於給定的狀態並讀入下一個輸入符號時,可以知道機器的下一個狀態是什麼。

 

然後我們可以把上題的描述轉換成一個DFAM1=Q,,,F),其中

①Q={123}

②={abc}

③描述爲


 

④1是起始狀態。

⑤F={2}

 

 

有窮自動機:



我們把問題搞清楚了,那麼久可以開始寫代碼了。

代碼如下:

#include<iostream>
#include<malloc.h>
#include<string.h>
using namespace std;
class DFA{
private:
int num_Q;//狀態個數
int acc_Q[100];//接受狀態集合
int t;//接受狀態個數 
int start_Q;//起始狀態
int num_E;//字母表個數
int next_E[100][100];//轉移函數
public:
void Init(int n,int m,int t,int accept[],int s[100][100]){//初始化DFA 
num_Q=n;
num_E=m;
for(int i=0;i<t;i++)
acc_Q[i]=accept[i];
start_Q=1;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
next_E[i][j]=s[i][j];
}
}
this->t=t;
}
bool go(char* w){//接受字符串的運行結果
bool result=false;//運行結果 
int q=start_Q;//當前狀態
for(int i=0;i<strlen(w);i++){
q=next_E[q-1][w[i]-'a'];
}
for(int i=0;i<t;i++){
if(q==acc_Q[i])
result=true;
}
return result;
}
};
int main(){
int n,m,t,a,s[100][100],accept[100];
char test[100][100],ch;
while(cin>>n>>m>>t>>a){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>s[i][j];
}
}
for(int i=0;i<t;i++){
cin>>accept[i];
}
for(int i=0;i<a;i++){
cin>>test[i];
}
//驗證
DFA dfa;
dfa.Init(n,m,t,accept,s);
for(int i=0;i<a;i++){
if(dfa.go(test[i]))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}
return 0;
} 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章