写博客的时候离中午下课还有40+分钟,所以让我先吼一句——肚子好饿啊,下面进入正题,咳咳咳
求一个模式串T在文本串S中出现了多少次
int m=T.length(),n=S.length();
暴搜算法的复杂度最坏的情况下是O(m*n)
辣么,如何减少重复的计算咧/kb
暴搜的时候我们一位一位的后移,但其实在一次比较之后,我们已知道几位的匹配情况,这时候就不用一位一位的后移,直接后移多位即可
如果当前模式串的T[1…x]已经跟文本串的S[p+1...p+x]完全匹配,但是T[x+1]与S[p+1+x]无法匹配。那么此时我们考虑如何运用已有的T[1…x]和S[p+1…p+x]完全匹配的信息。
考虑如果T[1…x]这个字符串,如果某个后缀T[x-k…x],跟前缀T[1…1+k]可以完全匹配,且T[x-k…x]可以和S[p+x-k..p+x]完全匹配,那么此时T[1…1+k]就可以和S[p+x-k…p+x]完全匹配
即T[1...1+k]=T[x-k...x]=S[p+x-k...p+x]
我们只需要找到最长的能跟前缀完全匹配的后缀,这样我们就能在匹配失败(失配)之后,直接将模式串开头移动到S[p+x-k]的位置
用next[i]表示以i结束的非前缀子串能够匹配的最长的前缀
那么只要算出这个next数组就行了
考虑在next[1]…next[i-1]都计算出来的情况下如何计算next[i]
如果next[i-1]的下一位能和S[i]匹配,那么
next[i]=next[i-1]+1
如果不能,那么我们需要找到next[next[i-1]]判断他的下一位能否和s[i]匹配。如果还不能,就继续往前找,直到找到0为止
|