[代码向]DFA与NFA两道编程题

[代码向]DFA与NFA两道编程题

1.DFA识别语言

在这里插入图片描述

样例(仅供参考):

3 2
1 2
2 -1
-1 -1
2 -1
aa
b
bab
#
0 0

DFA特点:

(1)没有空串ε的转换

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

因此只要构造好状态转换表,只要判断转化后的最终状态是否是接收状态就可以了.

代码如下:

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
const int N=51,M=27;
int trans[N][M]; //状态转换表
int acc[N]; //终态集合
int cnt; //终态个数

bool isAc(int fin_st){
    for(int i=0;i<cnt;i++){
        if(fin_st == acc[i]) return true;
    }
    return false;
}

int main(){
    //freopen("in.txt","r",stdin);
    int n,m;
    while(cin>>n>>m && (n && m)){
        // 读
        memset(trans,-1,sizeof(trans));
        memset(acc,0,sizeof(acc));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>trans[i-1][j]; //按题意这里读入的是i-1
        cnt=0;
        while(cin>>acc[cnt++] && acc[cnt-1]!=-1){;}
        cnt--;
        string query;
        while(cin>>query && query!="#"){
            int start=0;
            //状态转换
            for(int i=0; i<query.length(); i++){
                int next = trans[start][query[i]-'a'+1];
                if(next==-1){ //提早剪枝
                    start=-1;
                    break;
                }
                else start=next;
            }
            //状态到终态则AC
            if(isAc(start)) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
    }
    return 0;
}

2.NFA识别语言

在这里插入图片描述

NFA特点:

(1)存在空串ε的转换,比如从状态a经过空串ε到达b,但b也可以经过ε转化,到达其他状态,所以需要求ε的闭包

(2)输入的不确定性,对于同一输入符号,可能到达不同的状态(包括空串)

处理思路和DFA类似,不过DFA输入输出得到的是一个状态,而在NFA中是一个状态集合。

先给出伪代码:

在这里插入图片描述

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

数据如下:

4 3
{} {0,1} {0}
{} {} {2}
{} {} {3}
{} {} {}
3 -1
aaabb
abbab 
abbaaabb
abbb
#
0 0

代码如下:

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
const int N=51,M=27;
vector<int> move_[N][M]; //状态转换表
int acc[N]; //终态集合
int cnt,n,m; //终态个数,n is states, m is alphabet num
bool flag[N]; //求闭包时状态是否重复

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

void closure(stack<int> &ans,int n){ //求空串的闭包
    vector<int> all_(move_[n][0]);
    flag[n]=1;
    ans.push(n);
    for(int i=0;i<all_.size();i++){
        if(!flag[move_[n][0][i]]) closure(ans,move_[n][0][i]);
    }
}

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

int main(){
    //freopen("in.txt","r",stdin);
    char line[500];
    char *ps;
    char lash;
    stack<int> oldState,newState;
    while(scanf("%d %d%c",&n,&m,&lash) && (n && m)){
        memset(move_,0,sizeof(move_));
        memset(acc,0,sizeof(acc));
        for(int i=0;i<n;i++){
            gets(line);
            int h=0;
            ps=line;
            for(int j=1;j<=m;j++){
                for(;(line[h]!='}')&&(line[h]!='\0');h++){
                    if(line[h]<='9'&&line[h]>='0'){
                        int value=get_num(line,h);
                        move_[i][j-1].push_back(value);
                    }
                }
                h++; //再继续读下一个alpha
            }
        }
        cnt=0;
        while(cin>>acc[cnt++] && acc[cnt-1]!=-1){;}
        cnt--;
        string query;
        while(cin>>query && query!="#"){
            memset(flag,0,sizeof(flag));
            closure(newState,0);
            for(int i=0;i<query.length();i++){
                while(!newState.empty()){ // each state move alpha
                    oldState.push(newState.top());
                    flag[newState.top()]=0; // retrieve the flag
                    newState.pop();
                }
                while(!oldState.empty()){
                    for(int k=0;k<move_[oldState.top()][query[i]-'a'+1].size();k++){
                        if(!flag[move_[oldState.top()][query[i]-'a'+1][k]]){
                            closure(newState,move_[oldState.top()][query[i]-'a'+1][k]);
                        }
                    }
                    oldState.pop();
                }
            }
            if(isAc(newState)) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
    }
    return 0;
}

本博客参考以下博主并诚恳致谢

1.https://blog.csdn.net/dalewzm/article/details/14521283

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值