实现NFA算法(基于Python)

参考:Python实现DFA确定型有穷自动机和NFA非确定型有穷自动机相关算法_回炉重造P的博客-CSDN博客

https://github.com/huiluczP/finiteAutomata/blob/master/NFA.py

求解问题的思路

数据结构的设计

参考了NFA的定义,NFA是一个5-元组:M = (Q, ∑, Δ, s, F)

其中:Q是状态的有限集

  ∑是有穷字母表

  s是开始状态

  F含于Q,结束状态集

  Δ状态转移函数的集合

求解算法:

NFA识别字符串:某个字符串经过NFA,有多种可能路径,只要存在一种可以最终到达结束状态,则这个NFA就可以识别这个字符串。因此,只要得到这个字符串经过NFA最终到达的状态的集合,查看其中是否存在结束状态若存在,则NFA可以识别这个字符串,否则不可以

还要考虑空字符e的问题,某一状态经过空字符e可以到达的状态集合,即需要考虑某个状态的空闭包的问题若 I 是一个状态集合的子集,那么 I 会有一个空闭包集合,记作 ε-closure(I)。这个空闭包集合同样是一个状态集合,它的元素符合以下几点:I 的所有元素都是空闭包集合的元素对于 I 中的每一个元素,从该元素出发经过任意条 ε 弧能够到达的状态,都是空闭包集合的元素

在类NFA中,设计了四个函数,分别是read_string(),e_closure(),next_state(),match_final_state()。

函数read_string(input_str):读取输入的字符串,判断是否能够被NFA接受

函数e_closure(state):求取某个状态的空闭包(BFS的思想)

函数next_state(current_states, c):当前状态集经字符c到达的下一状态集

函数match_final_state(final_current_states):最终状态与接受状态匹配

"""设计识别字符串的NFA"""
import string
from collections import deque

class NFA:
    def __init__(self, states, symbols, t_state, start_state, final_state):     # 初始化
        self.states = states                    # 状态集
        self.symbols = symbols                  # 输入的符号集/字母表
        self.t_state = t_state                  # 状态转移函数
        self.start_state = start_state          # 开始状态
        self.final_state = final_state          # 结束状态

    def read_string(self, input_str):           # 读取字符串进入NFA鉴定
        for c in input_str:                     # 判断字符串满足字母表
            if c not in self.symbols:
                print('字符串中的字符不合法')
                return

        next_states = [self.start_state]
        for i in str:
            next_states = self.next_state(next_states, i)

        result = self.match_final_state(next_states)
        if result == True:
            print('NFA可接受该字符串')
        else:
            print('NFA不能接收该字符串')

    def e_closure(self, state):                 # 求取某个状态的空闭包
        d_state = deque()                       # 双端队列,存储中间状态
        empty_bag = []                          # 某个状态的空闭包
        d_state.append(state)
        empty_bag.append(state)
        while (len(d_state)):
            current_state = d_state[0]
            if current_state in self.t_state.keys():  # 如果当前状态存在
                if 'e' in self.t_state[current_state].keys():  # 若存在空字符转移
                    for s in self.t_state[current_state]['e']:
                        if s not in empty_bag:  # 如果状态不在空闭包内
                            d_state.append(s)   # 将经e到达的状态入队和加入空闭包
                            empty_bag.append(s)
            d_state.popleft()                   # 抛出当前状态
        return empty_bag

    def next_state(self, current_states, c):    # 当前状态经过某字符能够到达的下一状态的集合,包括空闭包
        next_states = []                        # 下一个状态集,包括下一个状态集的空闭包的集合
        for state in current_states:
            if state in self.t_state.keys():
                if c in self.t_state[state].keys():
                    n_states = self.t_state[state][c]
                    for s in n_states:          # 获取下一个状态集的空闭包
                        s_closure = self.e_closure(s)
                        for s_c in s_closure:   # 将空闭包的集合加入下一状态集合
                            if s_c not in next_states:
                                next_states.append(s_c)
        print('状态转移:')
        print(current_states, end=' ')
        print('-' + c + '->', end=' ')
        print(next_states)
        return next_states                      # 返回获取的下一状态的集合/通过字符c的状态集

    def match_final_state(self, final_current_states: list) ->bool :         # 最终状态匹配结束状态
        for state in final_current_states:
            if state in self.final_state:
                return True
        return False

if __name__ == '__main__':
    states = ['q1', 'q2', 'q3', 'q4']   # NFA状态集
    symbols = ['0', '1']                # NFA字母表
    t_state = {
        'q1': {
            '0': ['q1'],
            '1': ['q1', 'q2']
        },
        'q2': {
            'e': ['q3'],
            '0': ['q3']
        },
        'q3': {
            '1': ['q4']
        },
        'q4': {
            '0': ['q4'],
            '1': ['q4']
        }
    }                     # 状态转移函数
    start_state = 'q1'                  # 开始状态
    final_state = ['q4']                # 结束状态集

    while True:
        str = input("请输入测试的字符串:")
        if str == 'exit':
            break
        nfa = NFA(states, symbols, t_state, start_state, final_state)
        nfa.read_string(str)
  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值