中缀表达式转换为后缀表达式

本文详细阐述了后缀表达式的求值过程及中缀表达式转换为后缀表达式的方法,包括栈的应用、转换规则与实例演示。

在回复中说明不够清晰,在这里说明下,本文第一部分摘自《数据结构和算法分析-C语言描述》一书,只是做了一些概括和总结。


一、后缀表达式求值

后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。假定待求值的后缀表达式为:6  5  2  3  + 8 * + 3  +  *,则其求值过程如下:

1)遍历表达式,遇到的数字首先放入栈中,此时栈如下所示:

2)接着读到“+”,则弹出3和2,执行3+2,计算结果等于5,并将5压入到栈中。

3)读到8,将其直接放入栈中。

4)读到“*”,弹出8和5,执行8*5,并将结果40压入栈中。而后过程类似,读到“+”,将40和5弹出,将40+5的结果45压入栈...以此类推。最后求的值288。

 

 

二、中缀表达式转后缀表达式

2.1)规则

中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +。

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

 

2.2)实例

规则很多,还是用实例比较容易说清楚整个过程。以上面的转换为例,输入为a + b * c + (d * e + f)*g,处理过程如下:

1)首先读到a,直接输出。

2)读到“+”,将其放入到栈中。

3)读到b,直接输出。

此时栈和输出的情况如下:

 

4)读到“*”,因为栈顶元素"+"优先级比" * " 低,所以将" * "直接压入栈中。

5)读到c,直接输出。

此时栈和输出情况如下:

 

6)读到" + ",因为栈顶元素" * "的优先级比它高,所以弹出" * "并输出, 同理,栈中下一个元素" + "优先级与读到的操作符" + "一样,所以也要弹出并输出。然后再将读到的" + "压入栈中。

此时栈和输出情况如下:

 

7)下一个读到的为"(",它优先级最高,所以直接放入到栈中。

8)读到d,将其直接输出。

此时栈和输出情况如下:

 

9)读到" * ",由于只有遇到" ) "的时候左括号"("才会弹出,所以" * "直接压入栈中。

10)读到e,直接输出。

此时栈和输出情况如下:

 

11)读到" + ",弹出" * "并输出,然后将"+"压入栈中。

12)读到f,直接输出。

此时栈和输出情况:

 

 

13)接下来读到“)”,则直接将栈中元素弹出并输出直到遇到"("为止。这里右括号前只有一个操作符"+"被弹出并输出。

 

14)读到" * ",压入栈中。读到g,直接输出。

 

15)此时输入数据已经读到末尾,栈中还有两个操作符“*”和" + ",直接弹出并输出。

至此整个转换过程完成。程序实现代码后续再补充了。

 

 2.3)转换的另一种方法

1)先按照运算符的优先级对中缀表达式加括号,变成( ( a+(b*c) ) + ( ((d*e)+f) *g ) )

2)将运算符移到括号的后面,变成((a(bc)*)+(((de)*f)+g)*)+

3)去掉括号,得到abc*+de*f+g*+

<think>好的,我现在需要解决用户关于BM算法中好后缀规则的位移表的问题。首先,我得回忆一下BM算法的基本概念,确保自己理解正确。BM算法主要包含坏字符规则和好后缀规则,两者结合来提高匹配效率。用户特别提到的是好后缀规则的位移表,这应该是生成好后缀移动距离的关键部分。 接下来,我需要确认好后缀规则的具体机制。好后缀规则处理的是当模式串中存在与文本中匹配的后缀时,如何根据这个信息移动模式串。这一步可能涉及到两个表:好后缀位移表和坏字符位移表。用户的问题集中在位移表的生成,所以需要详细解释如何构建这个表。 然后,我想到好后缀规则需要考虑两种情况:当好后缀在模式串的前部分出现时,移动模式使得这两个部分对齐;如果不存在这样的重复,则需要找到最长的前缀,使其与好后缀的后缀匹配,然后进行相应的位移。例如,对于模式串"EXAMPLE",好后缀的处理可能需要查找前面的位置是否有相同的子串。 另外,生成位移表的步骤可能包括预处理模式串,记录每个可能的子串的位置,以便在匹配失败时快速查找位移量。这里可能需要用到数组或哈希表来存储这些信息,例如gs数组,其中每个索引对应好后缀的长度,值为需要移动的位数。 同时,用户可能希望了解具体的例子来加深理解。比如,举一个模式串的例子,逐步展示如何生成位移表。例如,以模式串"ABCAB"为例,分析好后缀出现的位置,并计算对应的位移值。这样可以帮助用户更直观地理解算法过程。 还需要注意,位移表的生成可能涉及不同的情况,如完全匹配的好后缀和部分匹配的前缀。这时,需要详细说明每种情况下的处理方式,并给出对应的位移计算方法。 此外,用户可能对实际应用或代码实现感兴趣,所以可以简要提及在代码中如何实现这一部分,例如使用预处理函数来生成位移表,并在匹配阶段使用该表进行高效的跳跃。 最后,要确保回答的结构清晰,分步骤解释好后缀规则位移表的生成过程,并结合示例和可能的代码片段(如Python实现),让用户能够逐步理解和应用相关知识。同时,需要引用提供的参考资料中的信息,例如引用[1]和[2]中关于BM算法的核心思想和比较,以增强回答的权威性。</think>### 关于BM算法中的好后缀规则与位移表 #### 1. 好后缀规则的核心思想 好后缀规则是BM(Boyer-Moore)算法的重要组成部分,用于在模式串与文本匹配失败时,根据已匹配的后缀(即“好后缀”)确定模式串的**最大安全位移距离**。其核心目标是跳过不必要的比对,直接移动模式串到可能匹配的位置[^1]。 #### 2. 好后缀位移表的生成步骤 位移表的构建分为两部分的预处理: 1. **好后缀在模式串中重复出现** 找到与好后缀完全匹配的最右子串,将模式串移动使该子串对齐当前匹配位置。 例如,模式串为$P = \text{ABCAB}$,假设已匹配的后缀$\text{AB}$,则位移量为$3$(将第二个$\text{AB}$移动到当前位置)。 2. **好后缀无重复但存在部分匹配前缀** 若好后缀未重复,则找到模式串的最长前缀,使其与好后缀的某个后缀匹配。 例如,模式串$P = \text{EXAMPLE}$,好后缀$\text{MPLE}$无重复,但前缀$\text{E}$与后缀$\text{E}$匹配,位移量为$6$。 #### 3. 位移表的具体实现 位移表一般通过**预处理模式串**生成,步骤如下: 1. **生成好后缀表(gs数组)** - 对于每个可能的后缀长度$k$($1 \leq k \leq m$,$m$为模式串长度),找到最右的与后缀匹配的子串位置。 - 若不存在,则找到最长前缀使其与后缀的某部分匹配。 例如,模式串$P = \text{ABCABC}$的gs表可能为: $$ \text{gs} = [6, 6, 6, 6, 3, 3] $$ 2. **结合坏字符表(bc数组)** 实际位移取**坏字符规则**和**好后缀规则**中的较大值,以最大化跳跃距离[^2]。 #### 4. 示例说明 以模式串$P = \text{EXAMPLE}$为例: - 好后缀$\text{MPLE}$在模式串中无重复,但前缀$\text{E}$与后缀$\text{E}$匹配,位移量为$6$。 - 若匹配失败位置在$\text{P}$(索引4),则根据gs表移动模式串。 #### 5. 代码片段(Python实现位移表) ```python def preprocess_good_suffix(pattern): m = len(pattern) gs = [0] * (m + 1) # 情况1:完全匹配的子串 for i in range(m): j = m - 1 while j >= 0 and pattern[j] == pattern[j - i - 1]: j -= 1 if j < 0: gs[i + 1] = m - i - 1 # 情况2:部分匹配的前缀 for i in range(m): length = 0 while pattern[length] == pattern[m - i - 1 + length]: length += 1 if length == i + 1: gs[m - i - 1] = m - length return gs ``` #### 6. 性能与应用 好后缀规则使BM算法平均时间复杂度达到$O(n/m)$,适用于长模式串和大字符集的场景(如DNA序列分析)[^3]。
评论 84
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值