• 利用子集构造法实现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
  • 相关阅读:
    heat模板
    Leetcode812.Largest Triangle Area最大三角形面积
    Leetcode812.Largest Triangle Area最大三角形面积
    Leetcode811.Subdomain Visit Count子域名访问计数
    Leetcode811.Subdomain Visit Count子域名访问计数
    Leetcode806.Number of Lines To Write String写字符串需要的行数
    Leetcode806.Number of Lines To Write String写字符串需要的行数
    Leetcode819.Most Common Word最常见的单词
    Leetcode819.Most Common Word最常见的单词
    Leetcode783.Minimum Distance Between BST Nodes二叉搜索树结点最小距离
  • 原文地址:https://www.cnblogs.com/kanjian2016/p/6786363.html
Copyright © 2020-2023  润新知