您的位置:首页 > 编程语言

DFA和NFA识别串的两道编程题

2013-11-08 15:09 246 查看
题目描述:



根据DFA特点:

(1)没有空串上的转换

(2)对于任意状态s,和输入符号a,只有一条标号为a的边离开s

那么只要构造好状态转换表,那么只要判断转化后的最终判断是不是接受状态就可以了

#include<iostream>
#include<cstdlib>
#include<memory.h>
#include<string>
using namespace std;

#define N 51
#define M 27
int trans
[M];
int acc
;
int count_;

bool isAc(int fin_st)
{
for(int i=0; i<count_; i++)
if(acc[i]==fin_st)
return true;
return false;
}
int main()
{
int n,m,i,j;

int start;

while(cin>>n>>m &&(n!=0 && m!=0))
{
memset(trans,0,sizeof(trans));
memset(acc,0,sizeof(acc));
for( i=1; i<=n; i++)
for(j=1; j<=m; j++)
cin>>trans[i-1][j];

count_=0;
while(cin>>acc[count_++] && acc[count_-1]!=-1){;}
count_--;

string query;
while(cin>>query && query!="#")
{
start=0;
for(i=0; i<query.length(); i++)
start=trans[start][query[i]-'a'+1];

if(isAc(start))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;

}
}
}

NFA 的题目描述



NFA的难度在于不确定性,同一个输入符号,可能到达不同的状态(包括空串)

所以需要ε闭包,求闭包需要注意,当你从状态a,经过 ε 转换到达b,但是b有可能经过ε转化,到达其它的状态

主要处理思路和DFA类似,不过DFA每次输入都得到的是一个状态,而在NFA中是一个状态集合

伪代码如下:



注意左边S和右边S的不同,分别代表新旧状态

详见代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<memory.h>
#include<string>
#include<string.h>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;

#define N 51
#define M 27

vector<int> move_
[M];
int acc
;
int count_,n,m;//n is states, m is alp num
bool flag
;

bool isAc( stack<int> &fin)
{
while(!fin.empty()){
for(int j=0; j<count_; ++j)
if(acc[j]==fin.top())
return true;
fin.pop();
}
return false;
}

void  clousre( stack<int> &ans,int m)
{
vector<int> stack_(move_[m][0]);

flag[ m]=1;
ans.push(m);
for(int i=0; i<stack_.size(); ++i)
{
if(! flag[ move_[m][0][i] ] )
clousre(ans, move_[m][0][i] );

}

}
int get_num(char * str,int &index)
{
int sum,i;
sum=0;
for(;(str[index]<='9')&& (str[index]>='0');index++)
{
sum=sum*10+str[index]-'0';
}
index--;
return sum;
}
int main()
{
int i,j,value,k,h;

stack<int> oldState,newState;
char line[500];
char *ps;
char lash;
while(scanf("%d %d%c",&n,&m,&lash) &&(n!=0 && m!=0))
{
memset(move_,0,sizeof(move_));
memset(acc,0,sizeof(acc));

for( i=0; i<n; i++)
{

gets(line);
h=0;
ps=line;
for(j=1; j<=m; j++){

for(;(line[h]!='}')&&(line[h]!='\0'); h++)
{
if(line[h]<='9' && line[h]>='0'){
value=get_num(line,h);
move_[i][j-1].push_back(value);
}
}
h++;

}
}
count_=0;//the number of accept state
while(cin>>acc[count_++] && acc[count_-1]!=-1){;}
count_--;

string query;
while(cin>>query && query!="#")
{

memset(flag,0,sizeof(flag));

clousre(newState,0);
for(i=0; i<query.length(); i++)
{

while(!newState.empty()){
oldState.push(newState.top());
flag[newState.top()]=0;
newState.pop();
}
//s(left)=s(right);
while(!oldState.empty()){
// start=trans[start][query[i]-'a'+1];
for(k=0; k<move_[ oldState.top() ][ query[i]-'a'+1 ].size(); ++k)
{
if(!flag[ move_[ oldState.top()  ][ query[i]-'a'+1 ][k] ])
clousre( newState, move_[ oldState.top() ][ query[i]-'a'+1 ][k]  );

}
oldState.pop();
}

}

if(isAc(newState))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;

}
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: