zoukankan      html  css  js  c++  java
  • NFA转DFA 子集构造法(Dev C++)

    参考资料:www.doc88.com/p-6843897482339.html

    代码:

    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #include<stack>
    using namespace std;

    int n;//n为边数
    int nk=0;//nk为空字符转换的边数
    int f[200];//状态属性标志0为初始态,1为终态,-1为中间态;
    int numof_Dtran=0;//最后得到的DFA中的状态数
    char Dtran[100][100];//DFA状态转换表;
    int first,accept;//初态   终态
    int useof_DFA[100];//标志构造出来的状态是否已存在
    int numof_char=0;//字母表中的字符个数
    int useof_char[256];//该转换字符是否用过
    char alpha[100];//输入字母表,#代表空串
    struct State{
        int H[100];//状态集合
        int count;//状态集合中的元素个数
        int flag;//是否是接受状态
        int mark;//状态编号
    };
    State DFA[100];//DFA状态集
     
    struct edge{
        int start,end;
        char c;
    }E[100],Ekong[100];//E保存所有的边,Ekong保存转换字符为空的边;
    void input(){
        ifstream fin("input.txt",ios::in);
        int i,s,e;
        char ch;
        fin>>n;
        cout<<"此状态转换有"<<n<<"条边"<<endl;
        fin>>first;
        cout<<"开始状态为:"<<first<<endl;
        memset(f,-1,sizeof(f));
        memset(useof_char,0,sizeof(useof_char));
        f[first]=0;
        cout<<"接受状态集为:";
        fin>>accept;
        while(accept!=-1){
            f[accept]=1;
            cout<<accept<<" ";
            fin>>accept;
        }
        cout<<" 起点,终点,转换字符(’#‘表示空字符):" <<endl;
        int k=0;
        for(i=0;i<n;i++){
            fin>>s>>e>>ch;
            cout<<s<<" "<<e<<" "<<ch<<endl;
            E[i].start =s;
            E[i].end =e;
            E[i].c =ch;
            //收集转换字母表
            if(ch!='#'&&!useof_char[ch]){
                alpha[numof_char++]=ch;
                useof_char[ch]=1;
            }
            if(ch=='#'){
                Ekong[nk].start =s;
                Ekong[nk].end =e;
                Ekong[nk].c =ch;
                nk++;
            }
        }
        
        cout<<"状态属性标志数组f情况!"<<endl;
        for( i=0;i<10;i++) cout<<f[i]<<" ";
        cout<<endl<<"*************"<<endl;
    }
    //状态t通过不定个#字符到达的状态!
    void arriveByone(int t,int result[],int& num){
        int k=0;
        int m=0;
        num=0;
        stack<int> S;
        S.push(t);
        int j;
        while(!S.empty() ) {
            j=S.top() ;
            S.pop() ;
            m=0;
            while(m<nk){//为什么m<nk ?nk是空字符转换的边数!
                if(Ekong[m].start==j){
                    result[num++]=Ekong[m].end ;
                    S.push(Ekong[m].end );  
                }
                m++;
            }
        }
    }
    //判断状态i是否在状态集T中
    bool check(int i,State T){
        int j;
        for(j=0;j<T.count;j++){
            if(T.H[j]==i)
              return true;
        }
        return false;
    }
    State closure(State T){
        stack<int> STACK;
        State temp;
        int i,j,k;
        for(i=0;i<T.count;i++){
            STACK.push(T.H[i]);//将状态集里面的每一个元素压入栈中
            temp.H [i]=T.H[i];
        }
        temp.count =T.count;
        temp.mark =T.mark;
        temp.flag =-1;
    //    cout<<"closure方法里:while循环之前:"<<temp.flag <<endl;
        while(!STACK.empty() ){
            int t=STACK.top() ;
            STACK.pop() ;
            //搜索状态T通过空字符到达的状态
            int search_result[100];
            int num;
            arriveByone(t,search_result,num);
            for(j=0;j<num;j++){
                if(!check(search_result[j],temp)){
                    temp.H [temp.count ++]=search_result[j];
                    STACK.push(search_result[j]);
                }
            }  
        }
    //    cout<<"closure方法里:while循环之后:"<<temp.flag <<endl;
        //判断完善之后的状态集是初态还是终态还是中间态!
        for(k=0;k<temp.count ;k++){
        //    cout<<temp.H[k]<<" ";
            if(f[temp.H [k]]==1){
                temp.flag =1;
                break;
            }
            if(f[temp.H [k]]==0){
                temp.flag =0;
                break;
            }
            
        }
    //    cout<<endl;
        //判断新形成的状态集和已形成的状态集是否有相同的!
        sort(temp.H ,temp.H +temp.count );
        for(i=0;i<numof_Dtran;i++){
            if(temp.count !=DFA[i].count)
               continue;
            sort(DFA[i].H,DFA[i].H+DFA[i].count);
            for(j=0;j<DFA[i].count;j++){
                if(DFA[i].H[j]!=temp.H [j])
                   break;
            }
            if(j>=DFA[i].count)
                 temp.mark =DFA[i].mark;
        }
        return temp;
    }
    State move(State T,char s){
        State temp;
        temp.count =0;
        temp.mark =T.mark;
        int i,j=0,k=0;
        for(i=0;i<T.count;i++){
            j=0;
            while(j<n){
                if(E[j].start==T.H[i]&&E[j].c ==s){
                    temp.H [temp.count ++]=E[j].end ;
                }
                j++;
            }
        }
        return temp;
    }
    //??????检查DFA中是否存在未被标记的状态,有则返回标号,否则返回-1;
    int check_inDFA(){
        int i;
        for(i=0;i<numof_Dtran;i++){
            if(!useof_DFA[i])
               return i;
        }
        return -1;
    }
    //检查状态T是不是已经在DFA状态集中
    bool check_whetherin_DFA(State T){
        int i,j;
        sort(T.H,T.H+T.count);
        for(i=0;i<numof_Dtran;i++){
            if(T.count!=DFA[i].count)
               continue;
            sort(DFA[i].H,DFA[i].H+DFA[i].count);
            for(j=0;j<DFA[i].count;j++){
                if(DFA[i].H[j]!=T.H[j])
                   break;
            }
            if(j>=DFA[i].count)
                return true;
        }
        if(i>=numof_Dtran)
           return false;
        else
           return true;
    }
    void child_method(){
        int m,n;
        //初始化状态转换表
        for(m=0;m<100;m++){
            for(n=0;n<100;n++){
                Dtran[m][n]='#';
            }
        }
        for(m=0;m<100;m++)
          DFA[m].flag=-1;
        //确定初态
        State S0,U;
        S0.flag =0;
        S0.count =1;
        S0.H [0]=first;
        State T;
        T=closure(S0);
        T.mark=0;
        T.flag=0;
        DFA[numof_Dtran++]=T;
        memset(useof_DFA,0,sizeof(useof_DFA));
        //开始确定化,找新形成的DFA开始推导!
        int j=check_inDFA();
        int k;
        while(j!=-1){
            useof_DFA[j]=1;
            for(k=0;k<numof_char;k++){
                State g=move(DFA[j],alpha[k]);
                U=closure(g);
                if(!check_whetherin_DFA(U)){
                    U.mark =numof_Dtran;
                    DFA[numof_Dtran]=U;
                    numof_Dtran++;
                }
                Dtran[DFA[j].mark][U.mark ]=alpha[k];
            }
            j=check_inDFA();
        }
    /* */
    }
    void print(){
        int i,j;
        for(i=0;i<numof_Dtran;i++){
           cout<<i<<":";
           for(j=0;j<DFA[i].count;j++){
                cout<<DFA[i].H[j]<<" ";
            }
            if(DFA[i].flag==1)
              cout<<" 终态 ";
            if(DFA[i].flag==0)
              cout<<" 初态";
            cout<<endl;
        }
        cout<<endl;
        for(i=0;i<numof_Dtran;i++){
            for(j=0;j<numof_Dtran;j++){
                if(Dtran[i][j]!='#'){
                    cout<<i<<"->"<<j<<" By "<<Dtran[i][j]<<endl;
                }    
            }
        }
        
    }
    int main(){
        input();
    /*    cout<<"%%%%%%%%%%%%%%%"<<endl;
        for(int i=0;i<n;i++){
            cout<<DFA[i].flag<<"  ";
        }
        cout<<endl<<"***********"<<endl; */
        child_method();
        cout<<endl;
        print();
    }

  • 相关阅读:
    失业状态,整理一下近期的面试问题 -- 直面自我
    nginx 学习 查一天不如问一句
    (10)kendo UI使用基础介绍与问题整理——MultiSelect
    kendo常用的实用方法(肯定有用得上的)
    (9)kendo UI使用基础介绍与问题整理——numerictextbox/基础说明
    去掉小数点后无效的0
    cmakelists编写样例
    visio 设计
    优化压测
    (转)语音处理基础知识
  • 原文地址:https://www.cnblogs.com/wtx2333/p/12519838.html
Copyright © 2011-2022 走看看