有穷自动机,也称有限自动机,作为一种识别装置,能够准确的识别正规集,即识别正规文法所定义的语言和正规式所表示的集合。引入有穷自动机理论,正是为词法分析程序的自动构造寻找特殊的方法和工具。
有穷自动机分为两类:确定的有穷自动机(Deterministic Finite Automata,DFA)和不确定的有穷自动机(Nodeterminister Finite Automata,NFA).
首先来说DFA。
一个确定的有穷自动机M是一个五元组:
(原谅我打不出这些字母,然后我就放了个图。ps:和书上字母不一样,不过意思差不多。)
具体的例子:
用矩阵表示DFA如下:
最开始的时候我写了一个实现最繁琐的小程序,就是这个
#include <iostream>
using namespace std;
class DFA
{
private:
char state;
public:
void initialize/*初始化*/(void){
state='S';
}
void transition/*转换*/(char);
bool in_terminal_state(void){/*终端*/
if(state=='Q')
return true;
else
return false;
}
bool in_fail_state(void){
if(state=='F')
return true;
else
return false;
}
DFA(void){
state='S';
}
};
void DFA::transition(char input){/*转换*/
switch(state){
case 'S':
switch(input){
case 'a':state='U';break;
case 'b':state='V';break;
default:break;
}
break;
case 'U':
switch(input){
case 'a':state='Q';break;
case 'b':state='V';break;
default:break;
}
break;
case 'V':
switch(input){
case 'a':state='U';break;
case 'b':state='Q';break;
default:break;
}
break;
case 'Q':
switch(input){
case 'a':state='Q';break;
case 'b':state='Q';break;
default:break;
}
break;
default:state='Q';break;
}
}
int main(){
char str[100];
char*ptr=NULL;
DFA M;
while(1){
M.initialize();
cout<<"please input the string you want to check;";
cin>>str;
ptr=str;
while(*ptr){
M.transition(*ptr);
ptr++;
}
if(M.in_terminal_state())
cout<<str<<"is acceptd by DFA."<<endl;
else if(M.in_fail_state())
cout<<str<<"is rejrcted by DFA."<<endl;
else
cout<<str<<"is not a complete legal string."<<endl;
}
return 0;
}
运行的结果是下面的样子:
突然发现如果输入aas也会出现被DFA接受的情况,一会继续修改,
接下来是最近怎么吃都吃不胖的隔壁宿舍毛毛同学的办法,他是在类中把状态输入了,不过好像得在vs2015里面跑才可以,可能是版本兼容性的问题。我在vs2010里发现里面的等于号显示错误。
ps:我发现这二货在类里面把数据初始化了,注意,类是一种数据类型,定义时系统并不为其分配内存空间。
下面是错误示例,不过还是有参考价值的。
#include<iostream>
#include<string>
using namespace std;
class DFA
{
public:
char K[4] = { 'S','U','V','Q' };//状态
char E[2] = { 'a','b' };//符号
char f[4][2] = { 'U','V','Q','V','U','Q','Q','Q' };//状态矩阵
char S;//初始状态
char Q;// 终状态
DFA() {}
int get_mark1(char x)//搜寻状态矩阵的横坐标
{
if ('S' == x)
return 0;
else if ('U' == x)
return 1;
else if ('V' == x)
return 2;
else if('Q' == x)
return 3;
}
int get_mark2(char y)//搜寻状态矩阵的纵坐标
{
if ('a' == y)
return 0;
else if('b' == y)
return 1;
}
};
int main()
{
DFA dfa;
string str;
char x, y;
x = 'S';
cin >> str;
int i = str.length();
for (int j = 0; j < i; j++)
{
y = str[j];
x = dfa.f[dfa.get_mark1(x)][dfa.get_mark2(y)];
}
cout << x << endl;
return 0;
}
又有一个版本,是我同桌郝宇璇的思路,把各种状态输入进去
#include "iostream"
#include "string"
using namespace std;
struct DFA{
private:
char state[4];
char letters[2];
char f[4][2];
char s;
char z;
public:
DFA();
bool testDFA(string &s);
};
DFA::DFA(){
int i;
cout<<"请输入DFA的状态:";
for(i=0;i<4;i++){
cin>>state[i];
}
cout<<"请输入DFA字母表:";
for(i=0;i<2;i++)
cin>>letters[i];
cout<<"输入转换后状态:";
for(i=0;i<4;i++)
for(int j=0;j<2;j++)
cin>>f[i][j];
cout<<"输入初始状态:";
cin>>s;
cout<<"输入终态:";
cin>>z;
}
bool DFA::testDFA(string &s){
char mstate='S';
int i=s.length();
for(int j=0;j<i;j++){
if(s[j]==letters[0]&&mstate==state[0]){
mstate=f[0][0];
continue;
}
if(s[j]==letters[0]&&mstate==state[1]){
mstate=f[1][0];
continue;
}
if(s[j]==letters[0]&&mstate==state[2]){
mstate=f[2][0];
continue;
}
if(s[j]==letters[0]&&mstate==state[3]){
mstate=f[3][0];
break;
}
if(s[j]==letters[1]&&mstate==state[0]){
mstate=f[0][1];
continue;
}
if(s[j]==letters[1]&&mstate==state[1]){
mstate=f[1][1];
continue;
}
if(s[j]==letters[1]&&mstate==state[2]){
mstate=f[2][1];
continue;
}
if(s[j]==letters[1]&&mstate==state[3]){
mstate=f[3][1];
continue;
}
}
if(mstate=='Q')
return true;
else return false;
}
int main(){
DFA d;
loop: string s;
cout<<"please input a string:"<<endl;
cin>>s;
if(d.testDFA(s)){
cout<<"right"<<endl;
system("pause");
goto loop;
}
else {
cout<<"false"<<endl;
system("pause");
goto loop;
}
return 0;
}
回头再好好研究下其他实现方法。。。。。
未完待续。。。。。。。。