精华内容
下载资源
问答
  • DFA确定化和最小化

    2021-03-23 15:56:15
    二、再将NFA转成DFA(子集法) 运用子集法的3个概念: (1 )状态集的ε-闭包: 状态集I中的任何状态s经任意条ε弧而能到达的所有状态的集合,定义为状态集I的ε -闭包,表示为ε−closure()ε -closure()ε−closure()...

    从正规式开始

    一、先将正规式转换成NFA

    通过下面的对应法则将正规式转换成NFA

    img

    例如:

    img

    二、再将NFA转成DFA(子集法)

    运用子集法的3个概念:
    (1 )状态集的ε-闭包: 状态集I中的任何状态s经任意条ε弧而能到达的所有状态的集合,定义为状态集I的ε -闭包,表示为εclosure()ε -closure()

    (2)状态集的a弧转换: 状态集I中的任何状态s经过一条a弧而能到达的所有状态的集合,定义为状态集1的a弧转换,表示为move(l,a)。

    (3)状态集的a弧转换的闭包a:lg=εclosure(move(l,a))lg= ε-closure(move(l,a))

    上面的正规式转换成NFA:

    img

    先从初态0开始求:

    【因为每个状态通过一条ε弧到达自己本身,所以求得ε的闭包包含自己】

    (1)求0的ε的闭包:经过任意条ε所能到达的状态,集合为{0,1,3,4,5,6,7,9}

    (2)求0的a弧转换:1经过a弧到达2,4经过a弧到达4,其余没有经过一条a弧到达某个状态,所以集合为{2,4}
    (3)求a弧转换的闭包:{2,4}分别经过任意条ε所能到达的状态,集合为{2,4,6,7,9}

    (4)求0的b弧转换:5经过b到5,7经过b到8,,其余没有经过一条b弧到达某个状态,所以集合为{5,8}

    (5)求b弧转换的闭包:{5,8}分别经过任意条ε所能到达的状态,集合为{5,6,7,8,9}
    0的ε-闭包:{0,1,3,4,5,6,7,9}
    0的a弧转换:{2,4}
    0的a弧转换的ε-闭包:{2,4,6,7,9}
    0的b弧转换:{5,8}
    0的b弧转换的ε-闭包:{5,6,7,8,9}
    现在列一个表格:
    (1)表格的列数为输入字符的个数+1,此题为a,b两个输入字符,所以为3列。
    (2)第一列第一行填写初态的ε-闭包(此题0的ε-闭包),第二列第一行填写初态的a弧转换的ε-闭包(此题0的a弧转换的ε-闭包),第三列第一行填写初态的b弧转换的ε-闭包(此题0的b弧转换的ε-闭包)…以此类推。
    (3)第一列的第二行以下填入上一行第二列以后的没有出现过的状态集。(此题第一行第二列第三列都没有出现在第一列中,将他们填入第一列)

    I IaI_a IbI_b
    {0,1,3,4,5,6,7,9} {2,4,6,7,9} {5,6,7,8,9}
    {2,4,6,7,9}
    {5,6,7,8,9}

    下图为填好的表:
    【新的终态的判断方法就是包含原来终态的集合就为终态,例如此题原来终态为9,所以包含9的集合就为终态,[双圈代表终态];
    新的初态就是包含原来初态的集合就为初态,例如此题原来初态为0,所以包含0的集合就为初态】

    img

    为表里的状态集重新标上号:

    img

    可以得到下面的图:

    img

    这个图是还不是最小化的DFA,还需要DFA最小化。但下面DFA最小化重新举例。

    三、将DFA最小化

    先了解几个概念:

    1.多余状态:对于一个状态SiS_i,若从开始状态出发,不可能到达改状态Si,则Si为多余(无用)状态。

    2.死状态:对于一个状态Si,对于任意输入符号a,若转到它本身后,不可能从它到达终止状态,则称Si为死状态。

    1,2都称为无关状态

    3.等价状态:若Si为自动机的一个状态,我们把从Si出发能导出的所有符号串的集合记为L(Si)。
    设有两个状态Si和Sj,若有LSi=LSjL(Si)=L(Sj),则称Si和Sj是等价状态。

    4.可区别状态:自动机中两个状态Si和Sj,如果它们不等价,则称它们可区别。

    5.两个状态(Si和Sj)等价的判断条件:

    (1)状态Si和Sj必须同时为终止状态或同时为非终止状态。即终止状态和非终止状态是可区别的。

    (2)状态Si和Sj对于任意输入符a∈Σ,必须转到等价的状态里,否则Si和Sj是可区别的。

    DFA的化简算法:对于DFA M=(S,Σ,f,S0,Z)
    (1)首先将DFA的状态集进行初始化,分成Π=(Z,S-Z);
    (2) 用下面的过程对Π构造新的划分Π new
    for (Π中每个组G) do //每个组都是一个状态集
    begin
    把G划分成小组,G中的任意两个状态Si和Sj在同一组中,当且仅当对于Σ中任意输入符号a ,Si和Sj的a转换是到同一组中,move(Si,a) ∈Gi ,move(Sj,a) ∈Gi。这样,只要Si和Sj的a转换是到不同的组中,则说明Si和Sj是可区别的,可进行划分。在Π new中用刚完成的对G的划分代替原来的G。
    end ; Π := Π new;
    (3)重复执行(2),直到Π中每个状态集不能再划分(Π new= Π)为止;
    (4)合并等价状态 ,在每个G中,取任意状态作为代表,删去其它状态;
    (5)删去无关状态,从其它状态到无关状态的转换都成为无定义。
    举例:

    img

    ①首次划分: Π0=({2,3,4,5},{0,1})

    ②在G={2,3,4,5}中:f(2,a)=1,f(4,a)=0(转向终态集{0,1});f(3,a)=3,f(5,a)=5(转向非终态集{2,3,4,5}),故{2,4}和{3,5}是可区别的,得Π1=({2,4},{3,5},{0,1});

    ③在G={2,4}中,f(2,a)=1,f(4,a)=0(转向终态子集),而f(2,b)=3,f(4,b)=5(转向非终态子集{3,5}),所以不可区别,不再进行划分;

    ④考察G={3,5},f(3,a)=3,f(5,a)=5(转向非终态子集{3,5}),f(3,b)=2,f(5,b)=4(转向非终态子集{2,4}), 所以不可区别,不再进行划分;

    ⑤考察G={0,1},f(0,a)=f(1,a)=1(转向终态集{0,1}); f(0,b)=2,f(1,b)=4(转向非终态子集{2,4}),所以不可区别,不再进行划分;

    ⑦进一步进行考察,可以发现每个子集都不能再划分了;

    ⑧消去等价状态:{0,1}用0表示,{2,4}用2表示,{3,5}用3表示,如右图所示

    ⑨去掉无关状态,因DFA M’中没有无关状态,所以下图即为最后结果。

    img

    展开全文
  • print('确定化状态表:','\n',tabulate(equal_list,headers=['I','Ia','Ib'],tablefmt='plain',numalign='right')) n_state = [] t_state = [] for i in range(len(d_queue)): if ed_state in d_queue[i][0]: t_...

    测试NFA状态转换图:

    当时测试的时候把把一些数据写死了,写在了一个data.txt文件里了,文件的内容是这样的;

    0 1 e
    0 7 e
    1 2 e
    1 4 e
    2 3 a
    4 5 b
    3 6 e
    5 6 e
    6 7 e
    7 8 a
    8 9 b
    9 10 b
    6 1 e

    源码:

    from tabulate import tabulate
    
    def e_closure(idx,c):
        closure = set()
        q = [idx]
        closure.add(idx)
        while len(q):
            t = q[0]
            for i in node_list[t]:
                if i[1] == c:
                    closure.add(i[0])
                    q.append(i[0])
            q.pop(0)
        return closure
    
    
    def n_closure(idx,c):
        closure = set()
        for i in node_list[idx]:
            if i[1] == c:
                closure.add(i[0])
        return closure
    
    # state_num = eval(input('状态数量:'))
    # char_num = input('字母表中字母:')
    # e_num = eval(input('定义式数量:'))
    # st_state = eval(input('开始状态:'))
    # ed_state = eval(input('结束状态:'))
    state_num = 11
    char_num = 'ab'
    e_num = 13
    st_state = 0
    ed_state = 10
    
    existed = []
    node_list = [[] for i in range(state_num)]
    d_queue =[]
    
    for line in open('data.txt','r'):
        xyw = line.strip('\n')
        pro = xyw.split(' ')
        x = eval(pro[0])
        y = eval(pro[1])
        w = (pro[2])
        node_list[x].append((y,w))
    if not st_state:
        for i in range(st_state):
            node_list.pop(0)
    for i in  range(len(node_list)):
        print(i,':',node_list[i])
    
    queue = []  # 状态I列表
    check_queue = []
    t = e_closure(st_state,'e')
    queue.append(t)
    check_queue.append(t)
    while(len(queue)):
        tt = queue[0]
        tmp = []
        tmp.append(tt)
        for c in char_num:
            I = set()
            for i in tt:
                I = I.union(n_closure(i,c))
            for i in I:
                I = I.union(e_closure(i,'e'))
            if I not in check_queue:
                queue.append(I)
                check_queue.append(I)
            tmp.append(I)
        d_queue.append(tmp.copy())
        queue.pop(0)
    
    print('子集法状态表:','\n',tabulate(d_queue,headers=['I','Ia','Ib'],tablefmt='plain'),end = '\n')
    
    equal_list =[]
    hash_map = dict()
    cnt = 0
    for i in d_queue:
        for j in i:
            j = str(j)
            if  j not in hash_map.keys():
                hash_map[j] = cnt
                cnt += 1
    for i in d_queue:
        process = []
        for j in i:
            j = str(j)
            process.append(chr(65 + hash_map[j]))
        equal_list.append(process.copy())
    
    print('确定化状态表:','\n',tabulate(equal_list,headers=['I','Ia','Ib'],tablefmt='plain',numalign='right'))
    
    n_state = []
    t_state = []
    
    for i in range(len(d_queue)):
        if ed_state in d_queue[i][0]:
            t_state.append(i)
        else:
            n_state.append(i)
    print('\n','第一次分组:')
    print('不含终态的子集:',n_state)
    print('含终态的子集:',t_state,'\n')
    
    vis = [0 for i in range(1000)]
    a = [0 for i in range(1000)]
    ans = [[] for i in range(1000)]
    nums = []
    ok = [0 for i in range(1000)]
    
    for i in n_state:
        vis[i] = 1
    for i in t_state:
        vis[i] = 2
    
    for i in range(len(equal_list)):
        n = 0
        for j in range(len(equal_list)):
            x = vis[j] * pow(10,len(equal_list[j]) - 1)
            for zz in range(1,len(equal_list[j])):
                aa = ord(equal_list[j][zz]) - ord('A')
                x += vis[aa] * pow(10,len(equal_list[j]) - zz - 1)
            if x == a[j]:
                n += 1
            a[j] = x
            ans[x].append(j)
            if ok[x] == 0:
                nums.append(x)
                ok[x] = 1
        ok = [0 for i in range(1000)]
        if n== state_num:
            break
        lenn = 1
        for j in range(len(nums)):
            for k in range(len(ans[nums[j]])):
                vis[ans[nums[j]][k]] = lenn
            lenn+=1
        ans = [[] for i in range(1000)]
        nums = []
    
    res = []
    
    for i in range(len(equal_list)):
        qwq = []
        qwq.append(chr(65 + i))
        qwq.append(vis[i])
        res.append(qwq.copy())
    
    print(tabulate(res,headers=['状态','集合'],tablefmt='plain',numalign='left'))
    

    给老师看可以加分!!!!

    展开全文
  • 很好~~~~~~~~~~~~~~~~~ 很难找~~~~~~~~~~~~~~~~~~
  • DFA确定化和最小化 从正规式开始 一、先将正规式转换成NFA 通过下面的对应法则将正规式转换成NFA 例如: 二、再将NFA转成DFA(子集法) 运用子集法的3个概念: (1 )状态集的ε-闭包: 状态集I中的任何状态s经...

    【编译原理】NFA到DFA转换的实例&&DFA确定化和最小化

    在这里插入图片描述

    从正规式开始

    一、先将正规式转换成NFA

    通过下面的对应法则将正规式转换成NFA


    在这里插入图片描述

    例如:


    在这里插入图片描述

    二、再将NFA转成DFA(子集法)

    运用子集法的3个概念:
    (1 )状态集的ε-闭包: 状态集I中的任何状态s经任意条ε弧而能到达的所有状态的集合,定义为状态集I的ε -闭包,表示为ε -closure()。

    (2)状态集的a弧转换: 状态集I中的任何状态s经过一条a弧而能到达的所有状态的集合,定义为状态集1的a弧转换,表示为move(l,a)。

    (3)状态集的a弧转换的闭包a: lg= ε-closure(move(l,a))

    上面的正规式转换成NFA:


    在这里插入图片描述

    先从初态0开始求:
      【因为每个状态通过一条ε弧到达自己本身,所以求得ε的闭包包含自己】
    (1)求0的ε的闭包:经过任意条ε所能到达的状态,集合为{0,1,3,4,5,6,7,9}
    (2)求0的a弧转换:1经过a弧到达2,4经过a弧到达4,其余没有经过一条a弧到达某个状态,所以集合为{2,4}
    (3)求a弧转换的闭包:{2,4}分别经过任意条ε所能到达的状态,集合为{2,4,6,7,9}
    (4)求0的b弧转换:5经过b到5,7经过b到8,,其余没有经过一条b弧到达某个状态,所以集合为{5,8}
    (5)求b弧转换的闭包:{5,8}分别经过任意条ε所能到达的状态,集合为{5,6,7,8,9}
    0的ε-闭包:{0,1,3,4,5,6,7,9}
    0的a弧转换:{2,4}
    0的a弧转换的ε-闭包:{2,4,6,7,9}
    0的b弧转换:{5,8}
    0的b弧转换的ε-闭包:{5,6,7,8,9}
    现在列一个表格:
    (1)表格的列数为输入字符的个数+1,此题为a,b两个输入字符,所以为3列。
    (2)第一列第一行填写初态的ε-闭包(此题0的ε-闭包),第二列第一行填写初态的a弧转换的ε-闭包(此题0的a弧转换的ε-闭包),第三列第一行填写初态的b弧转换的ε-闭包(此题0的b弧转换的ε-闭包)......以此类推。
    (3)第一列的第二行以下填入上一行第二列以后的没有出现过的状态集。(此题第一行第二列第三列都没有出现在第一列中,将他们填入第一列)

    I Ia Ib
    {0,1,3,4,5,6,7,9} {2,4,6,7,9} {5,6,7,8,9}
    {2,4,6,7,9}
    {5,6,7,8,9}

    下图为填好的表:
    【新的终态的判断方法就是包含原来终态的集合就为终态,例如此题原来终态为9,所以包含9的集合就为终态,[双圈代表终态];
    新的初态就是包含原来初态的集合就为初态,例如此题原来初态为0,所以包含0的集合就为初态】


    在这里插入图片描述


    为表里的状态集重新标上号:


    在这里插入图片描述


    可以得到下面的图:

    在这里插入图片描述


    这个图是还不是最小化的DFA,还需要DFA最小化。但下面DFA最小化重新举例。
    三、将DFA最小化

    先了解几个概念:
    1.多于状态:对于一个状态Si,若从开始状态出发,不可能到达改状态Si,则Si为多余(无用)状态。
    2.死状态:对于一个状态Si,对于任意输入符号a,若转到它本身后,不可能从它到达终止状态,则称Si为死状态。
    都称为无关状态
    3.等价状态:若Si为自动机的一个状态,我们把从Si出发能导出的所有符号串的集合记为L(Si)。
    设有两个状态Si和Sj,若有L(Si)=L(Sj),则称Si和Sj是等价状态。
    4.可区别状态:自动机中两个状态Si和Sj,如果它们不等价,则称它们可区别。
    5.两个状态(Si和Sj)等价的判断条件:
    (1)状态Si和Sj必须同时为终止状态或同时为非终止状态。即终止状态和非终止状态是可区别的。
    (2)状态Si和Sj对于任意输入符a∈Σ,必须转到等价的状态里,否则Si和Sj是可区别的。

    DFA的化简算法:对于DFA M=(S,Σ,f,S0,Z)
    (1)首先将DFA的状态集进行初始化,分成Π=(Z,S-Z);
    (2) 用下面的过程对Π构造新的划分Π new
    for (Π中每个组G) do //每个组都是一个状态集
    begin
    把G划分成小组,G中的任意两个状态Si和Sj在同一组中,当且仅当对于Σ中任意输入符号a ,Si和Sj的a转换是到同一组中,move(Si,a) ∈Gi ,move(Sj,a) ∈Gi。这样,只要Si和Sj的a转换是到不同的组中,则说明Si和Sj是可区别的,可进行划分。在Π new中用刚完成的对G的划分代替原来的G。
    end ; Π := Π new;
    (3)重复执行(2),直到Π中每个状态集不能再划分(Π new= Π)为止;
    (4)合并等价状态 ,在每个G中,取任意状态作为代表,删去其它状态;
    (5)删去无关状态,从其它状态到无关状态的转换都成为无定义。
    举例:

    在这里插入图片描述


    ①首次划分: Π0=({2,3,4,5},{0,1})
    ②在G={2,3,4,5}中:f(2,a)=1,f(4,a)=0(转向终态集{0,1});f(3,a)=3,f(5,a)=5(转向非终态集{2,3,4,5}),故{2,4}和{3,5}是可区别的,得Π1=({2,4},{3,5},{0,1});
    ③在G={2,4}中,f(2,a)=1,f(4,a)=0(转向终态子集),而f(2,b)=3,f(4,b)=5(转向非终态子集{3,5}),所以不可区别,不再进行划分;
    ④考察G={3,5},f(3,a)=3,f(5,a)=5(转向非终态子集{3,5}),f(3,b)=2,f(5,b)=4(转向非终态子集{2,4}), 所以不可区别,不再进行划分;
    ⑤考察G={0,1},f(0,a)=f(1,a)=1(转向终态集{0,1}); f(0,b)=2,f(1,b)=4(转向非终态子集{2,4}),所以不可区别,不再进行划分;
    ⑦进一步进行考察,可以发现每个子集都不能再划分了;
    ⑧消去等价状态:{0,1}用0表示,{2,4}用2表示,{3,5}用3表示,如右图所示
    ⑨去掉无关状态,因DFA M’中没有无关状态,所以下图即为最后结果。

    在这里插入图片描述

    image.png

    之前上面这个图画错了,现在图已经修改过了,谢谢提醒 :-D

    展开全文
  • 编译原理中的NFA确定化DFA最小化可运行代码以及思路解释
  • 本资源为一个src文件夹,有四个package: 1. Beans:NFA的DFA类 2.Utils:用于输入和输出的工具类 3.Service:核心代码。提供了确定化和最小化的代码实现 4.Test:可直接运行、测试(并且提供测试样例)
  • 编译原理——NFA确定化DFA最小化

    万次阅读 2018-04-05 14:12:54
    先完善DFA,再最小化DFA。 二、实验内容 确定NFA与DFA的存储格式。要求为3个以上测试NFA准备好相应有限自动机的存储文件。 用C或JAVA语言编写将NFA转换成DFA的子集构造法的程序。 准备3个以上测试DF...

    前言:这是我学习编译原理,课程实验的内容,课程早已结束,现整理发表。

    一、实验任务

    1. 存储NFA与DFA;
    2. 编程实现子集构造法将NFA转换成DFA。
    3. 先完善DFA,再最小化DFA。

    二、实验内容

    1. 确定NFA与DFA的存储格式。要求为3个以上测试NFA准备好相应有限自动机的存储文件。
    2. 用C或JAVA语言编写将NFA转换成DFA的子集构造法的程序。
    3. 准备3个以上测试DFA文件。(提示:其中一定要有没有最小化的DFA)
    4. DFA手动完善。(状态转换映射要是满映射)
    5. 用C或JAVA语言编写用等价划分法最小化DFA的程序。

    其实这部分内容要求没这么简单的,还有验证是否转换成功,怎么验证呢?只要你求出原来的和改后的某个子集(如长度小于某个N),再证实两个语言集合完全相同。不过当初我忘了这个了,后来验收的时候才发现没写,所以这部分我也不会加进来了。 ̄ω ̄=


    三、存储格式

    dfa

    3 // 字符集中的字符个数 (以下两行也可合并成一行)
    / * o // 以空格分隔的字符集。O代表任意非/和*的字符
    5 // 状态个数 (以下两行也可合并成一行)
    1 2 3 4 5 // 状态编号。若约定总是用从1开始的连续数字表示,则此行可省略
    1 // 开始状态的编号。若约定为1,则此行可省
    1 // 结束状态个数。若约定为1,则此行可省略
    5 // 结束状态的编号
    2  -1  -1 // 状态1的所有出去的转换。按字符集中的字符顺序给出。-1表示出错状态
    -1  3  -1
    -1  4   3
    5   4   3
    -1  -1  -1
    

    这部分不会照搬的,到后面输入会修改。不过大致还是这样的格式。


    四、程序设计

    • 实现思路

    想想还是写一点点吧,否则感觉缺点什么。

    nfa和dfa来看的大致都知道了,转换的话只要是用子集构造法。至于子集构造法怎么样的,大家自己查吧,我要说的就是注意空字符的到达处理,循环需要注意。
    而dfa最小化是最简单的吧,我反正就是先分为先分为是接受状态的集合和不是接受状态的集合,然后把转换状态相同的分为一个状态就可以了。当然,要修改状态的转换。

    • 文件说明:

        1. intArr.h intArr.cpp 数组类,用于实现数字集合的并,删除,查找
        2. NFA_To_DFA.h NFA_To_DFA.cpp dfa转nfa的类
        3. minimalDFA.h minimalDFA.cpp 最小化dfa的类
        4. main.cpp 主函数
      
    • 类设计说明

    1)intArr类

    class intarr
    {
    public:
        intarr();
        intarr(intarr &arr1);                   //复制构造函数
        int inline getSize(){return size;}      //获取集合大小
        void cleanArr();                        //清空集合元素
        void operator &= (int num);             //重载&=,并入单个元素
        void operator &= (intarr &arr1);        //重载&=,并入一个集合
        void getSort();                         //对集合元素从小到大排序
        int &operator[](int i);                 //重载[],可以向数组一样获得元素
        bool operator == (intarr &arr1);        //重载==,判断两个集合是否相等
        bool getNum(int num);                   //判断一个数字是否在集合中
        void delNum(int num);                   //删除一个数字
        int getNumber();                        //获得创建对象的个数
    
    private:
        int *arr=NULL;      //数组指针
        int size;           //数组大小
        static int number;  //创建对象的个数
    };
    
    

    2) NFA_To_DFA类

    dfa中的dfa集合

    struct state
    {
        int stateNum;        //这个状态的编号
        int *nextNum;        //根据输入字符将会指向哪些状态
        intarr nfaArr;       //NFA状态集
        bool isMake = false; //是否标记
        static int maxNum;   //最大状态标号
    };
    
    

    共享的一个dfa状态,作为一个中间状态用于创建新的dfa状态

    struct sstate
    {
        intarr nfaArr; //NFA状态集
        int stateNum = 0;
    };
    
    

    nfa转dfa的类

    class nfa_to_dfa
    {
      public:
        nfa_to_dfa(std::string fn); //默认构造函数
        void getIntArr(int num, std::string s);
        void closure_s();                     //空字符匹配
        void closure_T(int num, int charNum); //字符集匹配
        void inStates();                      //是否在当前DFA状态中了
        void read();                          //读取NFA数据
        void convert();                       //开始转换
        void output();
        ~nfa_to_dfa() {} //析构函数
    
      private:
        std::string charracters;          //nfa字符集
        int charrLength = 0;              //字符集的长度
        int statesNumber = 0;             //nfa状态个数,默认为0
        int currState = 1;                //开始状态编号,默认为1,不用输入
        int endNum = 1;                   //nfa接受状态个数,默认为1
        int *acceptStates = NULL;         //nfa接受状态集
        std::string **convertFrom = NULL; //转换表
        std::string filePath;             //文件输入对象
        sstate shareState;                //一个共享对象,用于转换
    
        int acceptNum = 0;      //转换出的dfa接受状态个数
        intarr DfaAcceptstates; //dfa接受状态集
    };
    
    

    3)minimalDFA类

    最小化dfa的一个状态,用结构体描述

    struct minState
    {
        static int maxNum;      //最大状态数
        intarr sameState;       //相同的输出的状态集合
        int  minNum;            //这个最小dfa的状态标
        int *nextState=NULL;    //不同输入字符的情况下指向不同状态的集合
        int isAcceptState=0;    //是否为接受状态
    };
    
    

    最小化dfa。算法思想:
    先将状态划分为接受状态和非接受状态。对于dfa中在输入相同的字符转到相同的状态的状态把这些状态划分到一组。

    class minDfa
    {
      public:
        minDfa(std::string str);  //构造函数
        void read();              //读取数据
        void divide();            //划分dfa
        void output();            //状态集
        bool isqueal();           //判断两个最小化dfa是否相等
    
      private:
        std::string charracters;  //字符集
        int charLength=0;
        int stateNum = 0;         //状态个数,默认为0
        int currState = 1;        //开始状态编号,默认为1
        int endNum = 1;           //接受状态个数,默认为1
        int *acceptState = NULL;  //接受状态
        int **convertFrom = NULL; //转换表
        minState *states;         //最小化dfa状态集
        std::string path;         //要读取文件的路劲
    };
    
    

    五、实验测试

    • 输入的nfa文件中

       第一行 为字符集 ,?表示空字符
       第二行 为状态个数,默认为从状态1开始,所以不用输入开始状态 
       第三行 为行为接受状态个数 
       第四行 为接受状态 
       第五行 开始为状态转换表。列为字符集,对应为一个二维数组,在哪个状态输入哪个字符转到哪个状态,-1为错误状态。
      
    • NFA转换为DFA

    1)nfa_to_dfa的输入文件nd:(aa|b)*(a|bb)*

    ab?
    4
    1
    3
    2,1,3,
    1,-1,-1,
    3,4,-1,
    -1,3,-1,
    
    

    2)在文件dfa_to_nfa中输出:

    ab
    5
    4
    1 2 3 5 
    {1,3,}		2 3 
    {2,3,}		1 4 
    {1,3,4,}		2 3 
    {4,}		-1 5 
    {3,}		5 4 
    
    

    3)作为minDfa的输入文件dfa:

    ab
    5
    4
    1 2 3 5 
    2 3 
    1 4 
    2 3 
    -1 5 
    5 4 
    
    

    4)最小化mindfa输出

    {1,3,}	1: 2 1 		isacceptstate:1
    {2,}	2: 1 3 		isacceptstate:1
    {4,}	3: -1 4 		isacceptstate:0
    {5,}	4: 4 3 		isacceptstate:1
    ***********
    

    六、实验总结

    来看怎么写的肯定要失望了,因为除了贴了些类的说明,也没有什么好参考的。我也知道我该写下是怎么写nfa转dfa,dfa怎么转换的,代码该怎么写,但是,太久了,我忘记了,你们可以直接看代码理解。还有如果对比是不是觉得我分文件啊,用结构体啊,用类啊写的好复杂啊,其实我也觉得挺复杂的,但是事实上大规模的代码实现分文件写是很好的,方便修改,如果一个文件维护修改会很麻烦,当初我也是第一次写这么多的分文件代码。但总的收获是不少的,中间遇到了许多问题,可以的话,试下这样写吧。


    七、资料下载

    具体代码见NFA_TO_NFA

    展开全文
  • 实验三 NFA确定化DFA最小化

    千次阅读 2017-11-25 21:35:54
    三、实验内容(1)确定NFA与DFA的存储格式。 要求为3个以上测试NFA准备好相应有限自动机的存储文件。(可利用实验一(二)的基础) (2)用C或JAVA语言编写将NFA转换成DFA的子集构造法的程序。 (3)测试验证程
  • 文章目录实验二 NFA确定化DFA最小化(4学时)(一)NFA转DFA(2小时)一、实验目的二、实验任务三、实验内容(二)DFA最小化(2小时)一、实验目的二、实验任务三、实验内容**四、通用NFA存储格式的建议(用以上的...
  • 编译原理实验二 NFA确定化DFA最小化一、实验目的二、实验任务三、实验内容1.NFA确定化2.DFA最小化四、实验准备1.NFA、DFA的存储格式2.测试样例的选择3.文件存储格式(以第三个样例为例)五、实验设计1.NFA确定化...
  • 一、实验标题:NFA确定化DFA最小化 二、实验目的:1. 学习和掌握将NFA转为DFA的子集构造法。2. 学会编程实现等价划分法最小化DFA。 三、实验内容:(一)NFA确定化(1)确定NFA与DFA的存储格式。要求为3个以上...
  • 第一部分 NFA确定化 一、实验目的 学习和掌握将NFA转为DFA的子集构造法。 二、实验任务 (1)存储NFA与DFA; (2)编程实现子集构造法将NFA转换成DFA。 三、实验内容 (1)确定NFA与DFA的存储格式。 要求为3个...
  • NFA确定化-DFA

    2018-11-07 10:44:20
    实验报告 编译原理之NFA确定化
  • 编译原理实现DFA和NFA,C语言 (凑字数字数字数字数字数)
  • 编译原理实验三:NFA确定化DFA最小化

    千次阅读 多人点赞 2019-01-29 20:59:42
    (一)NFADFA(2小时) ...(1)确定NFA与DFA的存储格式。要求为3个以上测试NFA准备好相应有限自动机的存储文件。(可利用实验一(二)的基础) (2)用C或C++语言编写将NFA转换成DFA的子集构造法的程...
  • nfa确定化 dfa to dfa 第四个
  • nfa确定化 dfa to dfa 第三个
  • 正则表达式转换为NFA,dfa,确定化 简单 方便实现
  • ps:实验要求文件的推荐 NFA 数据格式有大问题,对于NFA来说,因为NFA对于一个字符可能有多个转移状态,所以推荐的格式不能全部储存到。本人写的时候以为避开了雷,However...DFA(2小时) 一、实验目的 学习和掌握将N
  • NFA确定化为DFA 并最小化DFA

    千次阅读 2018-12-10 14:22:11
    把 NFA 确定化为 DFA 的算法实现 1)转换思路 由非确定的有限自动机出发构造与之等价的确定的有限自动机的办法是确定的有限自动机的状态对应于非确定的有限自动机的状态集合,即要使转换后的DFA的每一个状态对应...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 286
精华内容 114
关键字:

dfa确定化