本文主要涉及字符串的前中后缀表达式,以及KMP算法。
首先如我们所知道的,在C++中,一个字符串有三种表达形式。前缀、中缀和后缀形式。
区别在于:前缀表达式由操作数后面紧跟两个操作数构成的。如:*3 5
中缀表达式的操作数处于两个操作数之间。如:3*5
后缀表达式的操作数紧跟操作数,并处于末尾。如:3 5*
我们再谈谈这三种表达形式的转换。
个人认为中缀表达式转换成后缀表达式正确的转换方法:
遍历中缀表达式的每个节点,如果:
1、 该节点为操作数:
直接拷贝进入后缀表达式
2、 该节点是运算符,分以下几种情况:
A、 为“(”运算符:
压入临时堆栈中
B、 为“)”运算符:
不断地弹出临时堆栈顶部运算符直到顶部的运算符是“(”为止。并把弹出的运算符都添加到后缀表达式中
C、 为其他运算符,有以下步骤进行:
比较该运算符与临时栈栈顶指针的运算符的优先级,如果临时栈栈顶指针的优先级大于等于该运算符的优先级,弹出并添加到后缀表达式中,反复执行前面的比较工作,直到遇到一个栈顶指针的优先级低于该运算符的优先级,停止弹出添加并把该运算符压入栈中。
此时的比较过程如果出现栈顶的指针为‘(’,则停止循环并把该运算符压入栈中,注意:‘(’不要弹出来。
遍历完中缀表达式之后,检查临时栈,如果还有运算符,则全部弹出,并添加到后缀表达式中。
个人认为中缀表达式转换成前缀缀表达式正确的转换方法:
遍历中缀表达式的每个节点,如果: 1、该节点是为
操作数
:
压入栈中。
2、 该节点是运算符,分以下几种情况:
A、 为“(”运算符:
将临时堆栈的内容弹出,并放入前缀表达式中。
B、 为“)”运算符:
无操作 C、为其他运算符时,则直接放入前缀表达式中。
这里我给出一个中缀表达式:a+b*c-(d+e)
第一步:按照运算符的优先级对所有的运算单位加括号:式子变成了:((a+(b*c))-(d+e))
第二步:转换前缀与后缀表达式
前缀:把运算符号移动到对应的括号前面
则变成了:-( +(a *(bc)) +(de))
把括号去掉:-+a*bc+de 前缀式子出现
后缀:把运算符号移动到对应的括号后面
则变成了:((a(bc)* )+ (de)+ )-
把括号去掉:abc*+de+- 后缀式子出现
发现没有,前缀式,后缀式是不需要用括号来进行优先级的确定的。如表达式:3+(2-5)*6/3
但两种方法形成的后缀表达式的形式不同:
中缀表达式:a+b*(c-d)/f-e
形成的后缀表达式:
1. a b c d – f / * e – +
2. a b c d – * f / + e –
注意:前后缀表达式的计算不依照计算符的优先级,直接按照从左到右的计算。
KMP匹配算法源码。
问题描述:
串的前后缀问题。 KMP算法,Next数组
Next数组的作用在于存储当前字符之前的字符串中,有多大长度的相同前缀后缀
如Next[4]=3 意思是当前字符之前前后缀相同的字符数为3。
举一个例:字符串aaaabbcde。
它的Next数字为:-1、-1、-1、-1、3、0、0、0、0
所以KMP的匹配算法核心不同于暴力匹配方法之处在于如果当前第j个字符匹配失败,它并不是从新重头开始匹配,而是提取next数组中存储的当前字符之前的最长前缀的下一个字符开始再一次匹配。这种方法提高了整体性能。
- //修正后的求next数组各值的函数代码
- void get_nextval(char const* ptrn, int plen, int* nextval)
- {
- int i = 0;
- nextval[i] = -1;
- int j = -1;
- while( i < plen-1 )
- {
- if( j == -1 || ptrn[i] == ptrn[j] ) //循环的if部分
- {
- ++i;
- ++j;
- //修正的地方就发生下面这4行
- if( ptrn[i] != ptrn[j] ) //++i,++j之后,再次判断ptrn[i]与ptrn[j]的关系
- nextval[i] = j; //之前的错误解法就在于整个判断只有这一句。
- else
- nextval[i] = nextval[j];
- }
- else //循环的else部分
- j = nextval[j];
- }
- }
KMP
- //int kmp_seach(char const*, int, char const*, int, int const*, int pos) KMP模式匹配函数
- //输入:src, slen主串
- //输入:patn, plen模式串
- //输入:nextval KMP算法中的next函数值数组
- int kmp_search(char const* src, int slen, char const* patn, int plen, int const* nextval, int pos)
- {
- int i = pos;
- int j = 0;
- while ( i < slen && j < plen )
- {
- if( j == -1 || src[i] == patn[j] )
- {
- ++i;
- ++j;
- }
- else
- {
- j = nextval[j];
- //当匹配失败的时候直接用p[j_next]与s[i]比较,
- //下面阐述怎么求这个值,即匹配失效后下一次匹配的位置
- }
- }
- if( j >= plen )
- return i-plen;
- else
- return -1; }