
简介一份面向编译原理学习者的PDF资料对应蒋立源《编译原理》第三版第三章习题与答案解析聚焦文法、状态转换图、NFA与DFA、正规式等编译前端核心知识点。资源为单个PDF文件大小约2.97MB内容完整覆盖第三章从习题3-1到3-8的题目与推导过程既有原题剖析也有逐步推导与答案整理适合计算机专业学生课后巩固、考研复习或教师备课参考。目前已有1919人学习下载。解答部分细致展示了右线性文法等价构造、状态转换图与状态转换矩阵的互化、不同初终态设定下的3型文法描述、NFA确定化与最小化、含ε动作的NFA处理、以及利用正规式描述文法语言等关键步骤并配有改编后的状态命名与转换矩阵便于逐行对照。特别适合自学时对照教材逐题演练也可作为期末冲刺的速查手册。通过系统完成这些典型练习读者能更扎实地掌握有限自动机与形式语言的基础理论为后续词法分析程序设计与语法分析学习扫清障碍。1. 一份习题答案PDF为什么值得专门读第三遍期末周或考研复试着实被第三章卡住的人多半都搜过“编译原理第三章习题答案”而蒋立源版《编译原理》第三版的使用面很广这份标题带“修改后”的第三章习题与答案PDF正好对准词法分析这个分水岭章节。第三章不只是讲“什么是正规式”它把前面形式语言的基础变成了可操作的构造算法正规式转NFA、NFA转DFA、DFA最小化后面语法分析、语义分析全都建立在“能不能把语言变成一个确定的有穷自动机”之上。这份答案适合三类人刷题卡推导细节的、想核对旧版笔记里错误步骤的、正在写词法分析实验需要一个对照标准的人。它的价值不在于让你背结论而在于让你复算。2. 蒋立源版第三章到底在考什么词法分析、正规式与有穷自动机2.1 从正规式到DFA的四段路构造、去不确定、化简、运行第三章的题型翻来覆去只有四类但每类的答案写法差异巨大。第一类是“给定正规式构造NFA”考的是Thompson构造法要求把原子状态图按并、连接、闭包三种运算组合起来正确答案必须表现出明确的初态、终态以及闭包运算引入的空转移。第二类是“把NFA转成DFA”用的是子集构造法输出是一张以状态集合为行的转移表。第三类是“化简DFA”用的是划分法输出是一组合并后的等价状态。第四类不常单独出现但实验和考研里很常见给出一个DFA或NFA要求判断某个字符串是否被接受这本质上是状态转移表的模拟运行。把这四类归档之后再看答案思路会清楚很多。构造题判断对错看“每步是否合法”化简题看“终态是否被误合并”等价性证明题看“每一步用了哪条代数定律”。一份答案不可能只靠背就变成能力第三遍刷的时候我习惯先把每道题的题干关键词写到草稿纸上再判断它属于哪一类最后才翻PDF。这样可以避免只看答案的结构却不知道作者在回答哪个问题。文件名里没有说明是哪道题但答案的每页开头一般会有题目关键词正好用来做分类索引。2.2 为什么“修改后”三个字很重要答案类PDF最常见的问题不是思路错而是推导跳步和状态命名不统一。原始版本里经常出现“由上可得”这种黑匣子式写法状态编号写到一半换了命名表格的行列错位。标题里的“修改后”通常意味着这些硬伤被修过一遍所以它比普通流传版本更适合作对照。但修改后的文档也可能引入新的印刷错误这一点很多人会忽略。使用这份答案时要先做版本确认手上的教材是蒋立源主编、机械工业出版社的《编译原理第三版》第三版还是王生原等主编、清华大学出版社的《编译原理第3版》这两本书在电商和习题检索里经常混在一起第三章的习题编号完全不同用错答案比不用答案还糟。检索“编译原理第3版课后习题答案第三章”时会出现很多同名PDF确认主编姓名是最快的分辨方式。版本一致后还要注意印次差异第三版的某些印次调整过习题顺序题号对不上时以题目关键词为准。2.3 三类典型题的对错标准不一样构造题看步骤是否完整。答案如果直接给出最终状态图中间少了并运算的临时状态你就要在复算时自己补出来。NFA转DFA题看是否漏了空闭包凡是某个新状态集合只用了一次字符转移、没有回头求闭包的基本都要打问号。化简题看终态与非终态在第一步分组时有没有被分开这是最容易被错误答案带偏的地方。等价性证明题则要看两条一是每一步变换是否只使用了正规式代数里的合法定律比如交换律、结合律、分配律、幂等律二是结论是否真的回到“两个正规式接受相同语言”这个含义上。答案里如果用了“显然”“同理可得”这类词正是需要你停下来手推的地方。刷题时按这四类标准去检查而不是按题号顺序抄才能把PDF里的答案变成自己的判断力。第三章在期末考试和考研里占的分值不低但真正考的不是背答案而是给一个没见过的正规式照样能推出最小DFA。3. 对着答案复算一遍把PDF里的推导还原成可验证的步骤3.1 核对答案前的准备版本一致性与题号标注我拿到一份课后习题答案PDF不会直接从头翻到尾而是先做三件准备工作。第一确认教材主编和版次书名页上有蒋立源、第三版字样才算数第二把第三章里每道题的关键词抄到一张纸上比如“构造NFA”“求DFA”“化简”不抄题号只抄关键词第三先闭卷做一遍再打开PDF对照。顺序反过来的话很容易被答案的推导带着走最后变成“貌似看懂了”而不是“真的会了”。准备阶段还需要检查你手上的笔记版本。如果你用的是上一届流传的课堂笔记里面可能沿用了旧版答案的错误和这份“修改后”PDF冲突时不要急着改笔记先基于教材独立推一遍。我会准备两种颜色的笔黑色写自己的推导红色标注和PDF答案不一致的地方。这些红笔标注往往就是你和网传答案之间的真正分界线也是后面复习时最值得反复看的部分。版本确认无误后再进入复算效率会高很多。3.2 复算NFA构造画出状态图再查表正规式转NFA的题目答案里通常直接给出状态图。复算时要盯住三个易错点闭包运算是否增加了空转移边连接运算是否让前一个自动机的终态变成了后一个自动机的初态并运算是否引入了新的初态和终态。以正规式a(b|c)*d为例第一步要画出四个原子自动机a、b、c、d然后处理连接和闭包。b和c先并成一个选择结构接着对这个选择结果做星号闭包最后和a、d串起来。运算类型图形操作要点常见错误原子正规式每个字符对应一个初态到终态的边忘记状态编号选择新初态同时指向两个子自动机新终态接收两路遗漏其中一个分支连接前一个终态作为后一个初态的前驱初态和终态混淆闭包增加空转移形成回路新增初态与终态空转移边漏画对照答案时我一般先把答案里的状态图翻译成一张边表每条边写成“状态编号输入字符目标状态编号”的三元组。比如某个状态图里有2, ε, 3说明2号状态有一条空转移边指向3号。把整张图翻译成边表后再和自己画的状态图逐条比对很快就能找出少画或多画的那条边。答案状态编号和你的编号不同没关系只要边的相对关系一致就说明推导等价。3.3 复算子集构造法状态集合与转移表NFA转DFA是第三章里最机械、也最容易算错的一步答案里常见“I_0 ε-closure({x})”这类简写。复算时把每个简写都展开成完整的状态集合再用一张三列的表逐步推进新状态编号、当前状态集合、读入字符后到达的状态集合。以教材里常见的(a|b)*abb为例初始状态是1号它的 ε-closure 通常包含1号自身和经空转移可达的若干状态记作集合A。新状态状态集合abA{1, 2, 4}BCB{2, 3, 4}BDC{2, 4}BCD{5}--这张表的意思是从集合A读入a经过NFA的a转移和随后的空闭包到达集合B读入b则到达C。每次计算都要先走字符边再求ε-closure两个动作缺一不可。答案里如果跳过了某个集合的计算你就得自己把缺失的行补上。表完成后包含原始初态的集合就是DFA初态包含原NFA终态的集合就是DFA终态。注意D是终态行读入b后到达的集合里含有原终态5因此D行对应接受状态。3.4 复算DFA化简分组细化再合并DFA化简题的答案通常很简短但中间过程最容易踩坑。复算时严格按三步走第一步把DFA的状态分成终态组和非终态组第二步看组内每个状态读入某个字符后落到哪一组如果同组内两个状态落点不同立刻拆分第三步反复拆分直到组内不再变化每个组保留一个代表状态。答案里出现的“状态1和状态3可合并”背后的含义是它们对任意输入串都表现出相同的行为。我对照答案时有个习惯不用答案的分组顺序而是自己重新分一次。因为分组顺序不同代表状态的编号会不同但合并后的状态数和最终语言必须一致。如果你算出来的最小DFA状态数比答案多多半是漏了某个等价合并如果比答案少则很可能把不该合并的状态合并了尤其是终态和非终态混在一起的情况。验证是否合并错可以取一个语言边界上的字符串比如空串或单个字符分别跑两个DFA结果不一致就说明化简有问题。3.5 正规式等价性证明怎么检查等价性证明题在答案里最坑因为它经常只写结论和关键变换省略中间的代数定律。检查时先看每一步是否由一条已知定律支撑(a|b)* (b|a)*依据的是并运算的交换律(ab)*a a(ba)*依据的是结合律的推广。答案若出现“显然等价”你需要自己补出中间的DFA或代数推导。另一种可靠方法是把两个正规式分别转成最小DFA比较状态图和接收集合是否同构不过考试时通常没有这个时间平时练习倒是很值得做。4. 对着这份答案复习词法分析时容易踩的坑现象、原因与解决4.1 漏算空闭包子集构造法第一步就翻车现象复算NFA转DFA时你的状态集合比答案少一个或者转移表里某行顺不下去。 原因计算每个新集合时只走了字符转移边没有回过头求ε-closure。空闭包既包含状态自身也包含所有经由空转移能够到达的状态漏掉任何一个后继状态都会改变DFA结构。 解决每次得到字符转移后的临时集合都强制再做一次ε-closure并单独写一行“闭包后集合”。坚持三次以上这个动作就会变成肌肉记忆。4.2 化简时把终态和非终态合并了现象化简后的DFA能接受的字符串集合和答案不一致比如不能接受空串。 原因划分法的第一步分错了组把终态和非终态放进了同一组后续所有分裂都建立在错误分组上。 解决第一步永远先分成两组含终态的一组不含终态的一组。组内再分裂时每次都要写清楚“该状态读入a后落入第几组”。如果不确定某个合并是否合法找到这两个状态在语言上的一个分界串用第5章的模拟器跑一遍结果立刻见分晓。4.3 题号对不上不同印次的习题顺序有调整现象你翻到PDF里标注的第3.7题发现和教材上的第3.7题完全不是一回事。 原因教材在不同印次里调整过习题顺序或者题库排版重新编号过而答案PDF基于某一固定印次生成。 解决彻底抛弃题号索引改用题干关键词定位。在教材上把“构造NFA”“证明等价”这类词标出来再在PDF里找相同关键词的段落。靠关键词做映射比在题号上死磕省时间得多。4.4 “修改后”改了什么你不清楚旧笔记和答案打架现象课堂笔记推导结果和这份修改后PDF不一致你不知道该信哪个。 原因修改后版本可能修正了原版答案的跳步或错误也可能只是换了状态命名旧笔记则可能沿用了网上流传的错误推导。 解决谁对谁错不由版本新旧决定先把教材对应定理翻出来独立推一遍再回头对比两份材料。我会在笔记边缘写“旧版结论新版修改教材依据”三行字这样下次复习时不用重新争论。千万不要因为PDF写“修改后”就直接覆盖自己的推导过程。4.5 把正规式的优先级当成普通运算顺序现象写词法规则时把a|bc理解为(a|b)c或者把ab*理解为(ab)*结果DFA完全变形。 原因正规式优先级规定闭包运算最高连接次之选择最低。没有显式括号时ab*只能解析为a(b*)而不是(ab)*。 解决复算答案前先给正规式按优先级补全括号再开始构造NFA。一个不算技巧的技巧考试时多写冗余括号判卷老师不会因为括号多扣分但会因为你漏掉优先级含义直接判错。5. 怎么验证你从答案里学会的做法是对的实验与自检5.1 手写一个极简DFA模拟器验证结果刷完一份答案后最该做的事是把PDF里的DFA翻译成可运行的代码用一组边界字符串检验它。常见做法是写一个几十行的模拟器这里给出最小实现def run_dfa(trans, start, accepts, s): # trans: 字典键为(当前状态, 输入字符)值为目标状态 # start: 初态accepts: 终态集合s: 待测字符串 state start for ch in s: if (state, ch) not in trans: return False state trans[(state, ch)] return state in accepts # 以(a|b)*abb的最小DFA为例 t {(A,a):B, (A,b):C, (B,a):B, (B,b):D, (C,a):B, (C,b):C, (D,a):B, (D,b):C} print(run_dfa(t, A, {D}, abb)) # 应该接受 print(run_dfa(t, A, {D}, ab)) # 应该拒绝逻辑说明状态转移表被编码成字典run_dfa沿着输入串逐字符推进一旦某个(状态, 字符)组合在表中不存在直接返回假。整个字符串走完后看最终状态是否在终态集合里。参数start对应DFA初态accepts是包含所有终态的集合s是你要测的字符串。(a|b)*abb这个例子中“abb”应当被接受“ab”应当被拒绝符合肉眼判断。这里有个使用原则模拟器只用来验证答案不是用来替代手算。如果先跑代码再看推导你只能得到对错得不到方法。我会先手算子集构造法得到转移表再原样翻译成字典最后用模拟器跑几个边界串空串、纯a串、以abb结尾的长串。这样既能确认答案的DFA正确也能确认自己抄表时没有抄错。5.2 用编译原理实验的方式反向验证第三章很多人是在编译原理实验课上被词法分析器折磨时才重新翻开第三章答案的。常见实验要求是识别标识符、无符号数和关键字用Java实现一个能输出token序列的程序。这里头有不少学校的实验文档用的是“Java手工状态转移表”的路子广州大学等高校的课程实验里也能看到类似要求把词法规则转成DFA再用二维数组驱动识别。和5.1的字典模拟器原理一致只是字符变成了“字母、数字、运算符、空白”等类别。字符类别当前状态下一状态字母初态标识符态数字初态无符号数态字母标识符态标识符态非字母数字标识符态输出token并回到初态用法是把DFA的行列换成“状态×字符类别”单元格里写下一个状态编号。识别循环每读一个字符根据当前状态和字符类别查表走到终态就输出token然后回初态。这个练习能验证你对第三章掌握得是否扎实漏掉空闭包的人写出的转移表会让标识符中间断掉优先级理解错的人把a|bc类正规式翻译成DFA时会多出很多状态。如果PDF里的答案能顺利变成二维数组并跑通识别说明你已经把纸面推导变成了实际能力。5.3 从词法分析到符号表答案之外的下一个台阶第三章习题很少考符号表但词法分析器真正运行时识别token只是前半场。每个识别出的标识符都要去符号表里注册记录名字、类型、行号等信息关键字要区分是否保留字。编译原理符号表在实验里的典型流程是识别循环收到一个标识符token后先查符号表存在则更新引用信息不存在则插入新表项。这一步看似简单但和DFA直接相关DFA的终态类型决定了该查符号表还是直接输出token。比如识别到关键字状态就不进符号表而是直接生成保留字token识别到普通标识符终态才执行查表逻辑。所以学完第三章之后下一步可以做的不是接着刷第四章习题而是把这份PDF里某个DFA接上符号表逻辑。你甚至可以写一个极简的符号表类用哈希表存标识符名和行号让模拟器在每次进入终态时触发登记。做完这个串联再用答案核对正规式本身对不对才算把整章闭环。这也是为什么在实验课上已经吃透第三章的人写词法分析器很快他们不是在调规则优先级而是在实现一张已经验证过的状态转移表。6. 一个进阶用法把习题答案转成自己的知识点错题表第三遍刷这份答案时别再按题号顺序过了试试把PDF当成“错因对照表”来用。我会准备一张四列表格章节知识点、题目关键词、当时错在哪、答案用了哪几步。每核对一道题就填一行效率看起来比直接看答案慢但复习时只需要看这张表不用重新翻整份PDF。知识点题目关键词我当时错在哪答案关键步骤NFA转DFA给定NFA求DFA漏了ε-closure先闭包后字符转移DFA化简求最小DFA终态与非终态合并第一组按终态二分正规式等价证明a(b|c)*用了非法分配律化成同一NFA再比较“修改后”这份PDF的另一个用法是标记差异如果你的电脑里还留着旧版答案或者在打印店见过初版把改动过的题目在这张表里专门加一列“版本差异”。没有旧版也没有关系直接标“推导跳步已补全”或“状态命名统一”也能起到预警作用。因为你不知道修改过的内容里哪些是真正改错哪些只是格式化整理只有独立推演过的题才敢在考试时放心使用。最后说一个我自己的教训有一年考期前我只背答案不手推结果考场上一道NFA转DFA的化简题直接卡住平时看答案明明每一步都“看得懂”。从那以后我给自己定了一条规矩——答案只用来对照永远不替代推导。手推一遍哪怕和答案不一致也比背一遍答案更有价值因为不一致的地方恰恰是你和出题人理解的差异所在。这份PDF能不能发挥最大作用取决于你愿不愿意在它旁边留下自己算错的痕迹。希望这篇笔记对你有用也希望你刷完第三章后能对词法分析这件事建立起自己的直觉。本文还有配套的精品资源点击获取