zoukankan      html  css  js  c++  java
  • 利用子集构造法实现NFA到DFA的转换

    • 概述

    NFA非有穷自动机,即当前状态识别某个转换条件后到达的后继状态不唯一,这种自动机不便机械实现,而DFA是确定有限状态的自动机,它的状态转换的条件是确定的,且状态数目往往少于NFA,所以DFA能够比较方便的机械实现且识别能力方面也和NFA相当。本次实验采用子集构造法来实现不带空弧的由NFADFA的转换。

     

    子集构造法的算法如下:

    NFAM=(K,Σ,f,S0,Z),则构造相应的DFA  M=(Q,Σ,f,I0,F)
    ①取I0=S0
    ②对于状态集Q中任一尚未标记的状态qi={Si1,Si2,,Sim},SikK,做:
     (1) 标记qi
     (2) 对于每个a∈Σ,置
         T=f({Si1,Si2,,Sim},a)
         qj=εCLOSURE(T)
     (3) qj不在Q中,则将qj作为一个未加标记的状态添加到Q中,且把状态转移f(qi,a)=qj添加到M′。
    ③重复进行步骤②,直到Q中不再含有未标记的状态为止。对于由此构造的Q,我们把那些至少含有一个Z中的元素的qi作为M′的终态。

     

    对于如图所示的NFA其在文件中保存的信息如下

     

    转成DFA之后的形式为

     

    重命名为

    • 程序整体思路

    首先将文件中所给的NFA输入读入程序,在读入过程中将其以图的邻接表的形式保存,其中将状态转移条件记为该边的权值,每种状态记为图的结点,该状态识别状态转移条件(权值)之后到达的状态为该结点的邻接点。

     

    对于上面的例子,将其读入程序中后该图在程序中的逻辑存储结构(图的邻接表)如图所示,其中邻接点中第一个数字表示权值,第二个数字表示所连的结点。

    将图读入程序中后,再使用子集构造算法来完成由NFADFA的转化。

     

    对于每种状态,其数据结构定义为

    1 typedef struct state
    2 {
    3     set<int> Set;
    4     char name;
    5 }state;
    View Code

    其中set里存放该状态识别某个条件后所能到达的状态集合的下标,name里存该状态重命名后的名字。

     

    这些状态保存在状态数组States[max]中,状态数组States[max]数据结构定义为

    1 state States[max];
    View Code

    子集构造法的过程就是不断向状态数组States[ ]中,添加识别某个条件后,新的未出现的状态的过程。

     

    程序中函数说明

    void creatph(algraph &g,FILE *fpr):将文件内容读入程序,并将其转换为图的邻接表子函数。

    int change(algraph g,char p):将图中结点转化为对应下标子函数。

    state move(state s,int n,algraph g):求当前状态集合的转移集合,即求s状态识别字母n之后的状态集合。

    int equalSet(state m,state n):比较两个状态的set集合内容是否相等,不相等返回0,相等返回1

    void inStates(state &s):判断当前状态是否在States数组中存在,若存在,进行改名;若不存在,改名后加入States数组。

    void changeToD(algraph g,FILE *fpw):由NFA转到DFA的主控程序子函数。

    程序输入如下图所示

     

    程序输出如下图所示

     

    •  代码清单

      1 #include<stdio.h>
      2 #include<malloc.h>
      3 #include <iostream>
      4 #include <fstream>
      5 #include <cstring>
      6 #include<set>
      7 
      8 using namespace std;
      9 
     10 #define max 50//定义结点最大数量
     11 typedef char vertype;//定义结点值域为字符类型
     12 char buf[1024];//定义读文件内容时,程序缓冲数组
     13 int num;//记录有穷字母表元素的个数
     14 int length;//记录States数组的长度
     15 
     16 typedef struct arcnode//图的边信息
     17 {
     18     int adjvex;
     19     int weight;//边所对应的权值
     20     struct arcnode *next;
     21 }arcnode;
     22 
     23 typedef struct vnode//图的结点类型定义
     24 {
     25     vertype data;
     26     arcnode *next;
     27 }vnode,adjlist[max];
     28 
     29 typedef struct//图的定义
     30 {
     31     adjlist a;
     32     int vexnum,arcnum;
     33 }algraph;
     34 
     35 typedef struct state//状态的定义
     36 {
     37     set<int> Set;
     38     char name;
     39 }state;
     40 
     41 state States[max];
     42 
     43 int change(algraph g,char p)//将图中结点转化为对应下标
     44 {
     45     int i;
     46     for(i=0;i<g.vexnum;i++)
     47     {
     48         if(p==g.a[i].data)
     49             return i;
     50     }
     51     return -1;
     52 }
     53 
     54 void creatph(algraph &g,FILE *fpr)
     55 {
     56     int line = 0;
     57     while(!feof(fpr))
     58     {    
     59         fgets(buf,1024,fpr);
     60         if(strlen(buf)>1)//获取文件中图的结点个数
     61         {    
     62             int i = 0;
     63             while(buf[i]==' ')
     64             {
     65                 i++;
     66             }
     67             
     68             g.a[line].data=buf[i];
     69             g.a[line].next=NULL;
     70             line++;
     71         }
     72     }
     73     g.vexnum=line;
     74     
     75     rewind(fpr);//将文件指针返回到开头位置
     76     line = 0;
     77         arcnode *s;
     78 
     79     while(!feof(fpr))//再次扫描文件将边的信息添上,构造图
     80     {    
     81         int weight=0;//边所对应的权值,每一行权值都从0开始
     82         fgets(buf,1024,fpr);
     83         if(strlen(buf)>1)
     84         {
     85             for(int i=0;i<strlen(buf)-1;i++)
     86             {
     87                 if(buf[i]=='{')
     88                 {    
     89                     weight++;    
     90                     if(num<weight)
     91                         num=weight;
     92 
     93                     i++;    
     94                     if(buf[i]=='N')
     95                             i=i+4;
     96 
     97                     while(buf[i]!='}')
     98                     {    
     99                         if(buf[i]!=',')
    100                         {
    101                             //cout<<buf[i];////////////////////////////////
    102                             int x = change(g,buf[i]);
    103 
    104                             s=(arcnode *)malloc(sizeof(arcnode));
    105                             s->adjvex=x;
    106                             s->weight=weight;
    107                             s->next=g.a[line].next;
    108                             g.a[line].next=s;
    109                             //cout<<line;////////////////////////////////
    110                         }
    111                         i++;
    112                     }
    113                 }
    114             }
    115             line++;
    116         }    
    117     }
    118 
    119 }
    120 
    121 state move(state s,int n,algraph g)//求当前状态集合的转移集合,即求s状态识别字母n之后的状态集合
    122 {
    123     state temp;
    124     arcnode *m;
    125     set<int>::iterator itr;//迭代器
    126     for(itr = s.Set.begin();itr!=s.Set.end();itr++)//遍历当前s状态中集合元素 
    127     {
    128         int i = *itr;
    129         m = g.a[i].next;
    130         while(m)
    131         {
    132             if(m->weight==n)
    133             {
    134                 temp.Set.insert(m->adjvex);//cout<<m->adjvex<<" ";
    135             //    temp.name=s.name+1;//cout<<temp.name<<endl;
    136             }
    137             m=m->next;
    138         }
    139     }
    140     return temp;    
    141 }
    142 
    143 int equalSet(state m,state n)//比较两个状态的set集合内容是否相等
    144 {
    145     int flag = 1;
    146     if(m.Set.size()!=n.Set.size())
    147     {
    148         flag = 0;
    149         return flag;
    150     }
    151 
    152     set<int>::iterator itrm;
    153     set<int>::iterator itrn;
    154     for(itrm = m.Set.begin(),itrn = n.Set.begin();itrm!=m.Set.end();itrm++,itrn++)
    155     {
    156         int m = *itrm;
    157         int n = *itrn;
    158 
    159         if(m!=n)
    160         {
    161             flag = 0;
    162             break;
    163         }
    164     }
    165     return flag;
    166 }
    167 
    168 void inStates(state &s)//判断当前状态是否在States数组中存在,若存在,进行改名;若不存在,改名后加入States数组
    169 {
    170     int flag = 0;
    171     if(length==0)
    172     {
    173         States[0]=s;
    174         States[0].name='A';
    175         length++;
    176     }
    177     else
    178     {
    179         for(int i=0;i<length;i++)
    180         {
    181             //cout<<equalSet(States[i],s);
    182             if(equalSet(States[i],s)==1)//若存在,进行改名
    183             {
    184                 s.name=States[i].name;
    185                 flag = 1;
    186                 break;
    187             }
    188         }
    189 
    190         if(flag == 0)//若不存在,改名后加入States数组
    191         {
    192             s.name=States[length-1].name+1;
    193             States[length]=s;
    194             length++;
    195         }
    196     }
    197 }
    198 
    199 void changeToD(algraph g,FILE *fpw)
    200 {
    201     state s,temp;
    202     s.Set.insert(0);
    203     s.name='A';
    204 
    205     inStates(s);
    206 
    207     for(int i=0;i<length;i++)
    208     {    
    209         cout<<"{";
    210         fprintf(fpw,"{");
    211 
    212         set<int>::iterator itr;//迭代器
    213         for(itr = States[i].Set.begin();itr!=States[i].Set.end();itr++)//遍历当前s状态中集合元素 
    214         {
    215             int i = *itr;
    216             cout<<g.a[i].data<<",";
    217             fprintf(fpw,"%c,",g.a[i].data);
    218         }
    219 
    220         cout<<"}";
    221         fprintf(fpw,"}");
    222 
    223         cout<<States[i].name;
    224         fprintf(fpw,"%c",States[i].name);
    225 
    226         for(int j=1;j<=num;j++)
    227         {
    228             temp = move(States[i],j,g);
    229             inStates(temp);    
    230             //查看temp状态的set集合
    231             /*    
    232             set<int>::iterator itr;//迭代器
    233             for(itr = temp.Set.begin();itr!=temp.Set.end();itr++)//遍历当前s状态中集合元素 
    234             {
    235                 int i = *itr;
    236                 cout<<i<<" ";
    237             }*/    
    238             cout<<temp.name;
    239             fprintf(fpw,"%c",temp.name);    
    240         }
    241         cout<<endl;    
    242         fprintf(fpw,"
    ");
    243     }
    244 }
    245 
    246 
    247 int main()
    248 {
    249     algraph g;
    250 
    251     FILE *fpr = fopen("F:\test.txt","r");
    252     FILE *fpw = fopen("F:\testOutput.txt","w");
    253     
    254 
    255 /*    FILE *fpr = fopen("test.txt","r");
    256     FILE *fpw = fopen("output.txt","w");*/
    257 
    258     creatph(g,fpr);
    259 
    260     //create测试
    261     /*
    262     for(int i=0;i<g.vexnum;i++)
    263     {
    264         cout<<g.a[i].data<<endl;//////////////////
    265 
    266     }
    267     */
    268 
    269     changeToD(g,fpw);
    270     //move测试
    271     /*
    272     state s;
    273     s.Set.insert(0);
    274     s.Set.insert(2);
    275     s.Set.insert(3);
    276     s.mark=1;
    277     s.name='B';
    278 
    279     move(s,2,g);
    280     */
    281     return 0;
    282 }
    View Code
  • 相关阅读:
    redis(二)高级用法
    redis(一) 安装以及基本数据类型操作
    RabbitMQ(五) -- topics
    JS实时数据运算
    Access数据库中Sum函数返回空值(Null)时如何设置为0
    asp检测数字类型函数
    MVC:从客户端中检测到有潜在危险的 Request.Form 值 的解决方法
    WIN8系统安装软件时提示"扩展属性不一致"的解决方法
    免费的网络扫描器-Advanced IP Scanner
    中国电信大亚DP607光猫破解,设置路由,wifi!关闭远程管理,改连接限制,SN码查询!
  • 原文地址:https://www.cnblogs.com/kanjian2016/p/6786363.html
Copyright © 2011-2022 走看看