为语言L={a^i b^j c^k | j=i+2k}构建PDA遇问题,请求协助
修复下推自动机(PDA)以正确识别语言L={a^i b^j c^k | i,j,k≥0且j=i+2k}
问题分析
当前实现的PDA错误接受了字符串bc,而根据语言规则,bc中i=0,j=1,k=1,不满足j=i+2k(1≠0+2×1),因此不应被接受。问题出在c的处理逻辑:每个c仅抵消了1个额外的b(对应栈中的B),但规则要求每个c需抵消2个额外的b。
错误路径解析
处理bc时的错误路径:
- 状态0读入
b,栈底为Z,压入B后进入状态1,栈变为[B, Z] - 状态1读入
c,弹出B后进入状态2,栈变为[Z] - 状态2通过空转移直接进入终态3,导致字符串被错误接受
修正方案
核心调整点:
- 每个c必须抵消2个B(对应2个额外的b),需分两步完成B的弹出
- 移除状态2直接到终态的空转移,仅允许状态1在栈为空(仅剩余Z)时进入终态
修正后的Scala代码
PDA = PDA( states = Set(0, 1, 2, 3), symbols = Set('a', 'b', 'c'), alphabets = Set("A", "B"), trans = Map( // 处理a:每个a压入一个A到栈中 (0, Some('a'), "Z") -> Set((0, List("A", "Z"))), (0, Some('a'), "A") -> Set((0, List("A", "A"))), // 空字符串直接接受 (0, None, "Z") -> Set((3, List("Z"))), // 从状态0处理b:匹配a对应的b(弹出A),或开始记录额外的b(压入B) (0, Some('b'), "A") -> Set((1, List())), (0, Some('b'), "Z") -> Set((1, List("B", "Z"))), // 状态1处理b:继续匹配a对应的b,或记录额外的b (1, Some('b'), "A") -> Set((1, List())), (1, Some('b'), "Z") -> Set((1, List("B", "Z"))), (1, Some('b'), "B") -> Set((1, List("B", "B"))), // 状态1仅在栈为Z时可进入终态 (1, None, "Z") -> Set((3, List("Z"))), // 处理c第一步:弹出第一个B,进入状态2 (1, Some('c'), "B") -> Set((2, List())), // 处理c第二步:弹出第二个B,回到状态1(完成一个c对应2个b的抵消) (2, None, "B") -> Set((1, List())), // 移除状态2到终态的空转移,避免单个c抵消单个B后直接接受 ).withDefaultValue(Set()), initState = 0, initAlphabet = "Z", finalStates = Set(3), )
修正逻辑说明
- a的处理:保持原有逻辑,每个a压入一个A,后续用b匹配弹出。
- b的处理:保持原有逻辑,匹配a对应的b时弹出A,额外的b压入B。
- c的处理:每个c需要分两步弹出两个B:
- 第一步:状态1读入c,弹出第一个B进入状态2
- 第二步:状态2通过空转移弹出第二个B,回到状态1
- 若栈中仅有1个B,第二步无法执行,无法回到状态1,也就无法进入终态,从而拒绝
bc这类不符合规则的字符串。
- 终态转移:仅允许状态1在栈仅剩余Z时进入终态,确保所有需要匹配的符号都已正确抵消。
内容的提问来源于stack exchange,提问作者Youngheon Jeong
相关产品推荐
相关产品推荐

