第4章学习小结
串的模式匹配
一、BF算法 —— 暴力匹配
1、当前匹配,++i;++j;
2、当前不匹配,i=i-j+2;j=1;
二、KMP算法
首先是主串s 和模式串t 的比较,当前比较的是主串s的第i个和模式串的第j个,若s[i]==t[j]; 则++i; ++j; 这里i,j为位置,而非下标
当出现不匹配时,i不回溯(停留在当前位置),通过next数组找到下一个和s[i]比较的数的下标k;
由于模式串t的任一元素都有可能和s在匹配时,失配,所以要为t的每个元素找好一个“后备军”k 以应对t[j]和s[i]不匹配的情况。于是这里用next数组来存储这些"后备军“k,当s[i]!=t[j],则j退到第二选择k,再进行s[i]和s[k]的比较
明显k不是随便的一个数,作为t[j]的“后备军”,满足:k之前的k-1个数和j前的k-1个数一一相等,只有这样t[k]才能而直接和当前已和t[i]失配的s[i]比较,而免去前k-1次和s的比较
以下是关于next数组的理解
设此时j的“后备军”为k,即next[j]=k,那么要求next[j+1]的值,则需要比较t[j]和t[k]的值,即比较t[j]和t[k]
若t[j]==t[k],那么next[j+1]=next[j]+1;否则再退一步,比较t[j]和t[next[k]]直到比较到相等的,或比到最后的最后:t[j]!=t[1],则next[j]=1
void get_next(SString T, int next[]) {//求模式串T的next函数值并存入数组next i=1;next[1]=0;j=0; while(i<T.length) { if(j==0 || T.ch[i]==T.ch[j] { ++i; ++j; next[i]=j; } else j=next[j]; } }
然而,以上函数然存在缺陷,例如在面对主串为“aaabaaaab",模式串为”aaaab“时,仍浪费了时间
于是改进为
void get_next(sstring t,int Next[]) //求模式串t的next函数值并存入数组next { int i=1,j=0; Next[1]=0; while(i<t.length) { if(j==0 || t.ch[i]==t.ch[j]) { ++i; ++j; if(t.ch[i]!=t.ch[j]) Next[i]=j; else Next[i]=Next[j]; } else j=Next[j]; }
不同的是,若当前比较时t.ch[i]!=t.ch[j],则Next[i]的值再退一步到Next[j]的值
心得体会
花了很长一段时间还是被如何next数组难倒,看了很多人关于这方面的代码,还是没能理解,有的人next数组从-1开始,有的人从0开始,看来看去,整个人思维很混乱,因为一开始自己对next数组就没有理解清楚,越乱越急。后来还是回归书本,自己用一个模式串带函数进去走一遍,然后就慢慢理解的其中的关系,看来还是要有自己的理解先,实在不行就用土办法,土办法还是挺好用的 ^_^
关于上次确定的目标及接下来的目标
这回练习的代码数量增多了,具体实施的时候还参考了很多其他人的代码,在一道需要C语言的函数题中参考了关于C的输入输出的资料:https://www.cnblogs.com/JCSU/articles/1306308.html
接下来的目标还是多练习💪