思路
-
暴力算法
-
S[N] p[M]
-
S[]待匹配的长串
-
p[]模板串短串
-
-
变量说明
-
t=0/1都可以,这里单独拉出来说明01都可
-
bool flag;
-
-
for(int i=t;S[i];i++) { flag=true; for(int j=t;p[j];j++) { if(s[i]!=p[j] )flag=false;break; } }
-
-
-
-
-
i j
-
i前为匹配完的区域(无符合要求)
-
i----j判断2串相同的区域
-
j为不相同的开始
-
暴力做法为到j发现不满足,退回i再+1开始再次匹配串
-
-
-
KMP算法
-
1.
-
变量说明
-
S[N] p[M]
-
S[]主串
-
p[]子串
-
字串从主串的第i位开始匹配到k+1位时不匹配停下
-
当第k+1位不匹配时(图黄C) Next[k]存储着字串新的开头可以移动的位数
-
即从(i+Next[k])重新匹配
-
-
-
获取Next[]
-
1.
-
2.
-
一个人能能走的多远不在于他在顺境时能走的多快,而在于他在逆境时多久能找到曾经的自己-KMP
-
条件
-
串为S[]
-
i已知
-
t已知
-
数组从1开始
-
-
图分析
-
next[i] 匹配的最长串长 推导1 推导2 推导3 推导4 推导5 next[4] 0 next[5] 1 0+1 0+1 S[1]=S[5] S[0]=S[5] S[next[4]+1]=S[5] next[6] 2 0+1+1 1+1 S[2]=S[6] S[1+1]=S[6] S[next[5]+1]=S[6] next[7] 3 0+1+1+1 2+1 S[3]=S[7] S[2+1]=S[7] s[next[6]+1]=S[7] next[i-1] t -- -- -- -- next[i] (顺境) t+1 -- t+1 S[t+1]=S[i] S[next[i-1]+1]=S[i] next[j-1] x -- -- -- -- -- next[j] (逆境) -
说明
-
next[i] 的求取为顺境情况
-
next[j]的求取为逆境情况
-
前后缀相同为S[1,N]=S[M-(N-1),M] S[1,N] 表示从S[1]S[2]S[3]...S[N]
-
-
1.顺境
-
next[i-1]=t
-
顺境条件 S[t+1]=S[i] 即 S[next[i-1]+1]=S[i]
-
顺境结果 next[i]=next[i-1]+1
-
-
2.逆境
-
逆境条件 不满足顺境条件即为逆境
-
逆境结果 无法使用next[i]=next[i-1]+1 获取next[i]值
-
-
逆境(S[j]!=S[x+1])处理
-
条件1. next[j-1]=x
-
条件2. 因为逆境的上一步是已经操作完毕的,我们由next[j-1]=x是匹配的最长串长可知 S[j-1-x+1]---到--->S[j-1] 与S[1]---到--->S[x] 完全相同
-
逆境时多久能找到曾经的自己
-
因为next[j]要存匹配的最长串长,即为S[1]--->S[] = S[]--->S[j]
-
因为条件2可知我们判断的 S[j-x]...S[j-2] S[j-1] 与S[1]...S[x-1]S[x]对称
-
图
-
此时因为逆序需要重新判断,但是S[j]前可能存在S[j-2]S[j-1]S[j]与S[1]S[2]S[3]的情况这时候我们需要倒回去找
-
倒回去时当next[j-1]=0 时,next[j]必然为0或1, S[j]==S[1] 则next[j]=1 S[j]!=S[1]则next[j]=0
-
倒回去时当next[j-1]!=0时,因为逆境导致我们的next[j]的获取不能按照常规顺境处理,且我们非暴力穷举的处理方法都依赖顺境,这时候我们需要找到曾今的自己
-
这里next[j-1]=x
-
S[1] S[2]... S[x-1] S[x]
-
S[j-x] S[j-x+1]...S[j-2 ] S[j-1] 这时候可能看不出什么,那我再加一点点东西
-
S[1] S[2]... S[x-1] S[x] S[x+1]
-
S[j-x] S[j-x+1]...S[j-2 ] S[j-1] S[j]
-
S[j]遇到的逆境和S[x+1]遇到的逆境那么相同,曾今的自己是什么已经可以得知了
-
过去的我不是现在的我,所以我们处理S[j]真正的方法是借用S[x+1]求next时用到的 next[x]
-
next[x+1] 求取过程:1.判断S[next[x]+1]==S[x+1]
-
next[j] 求取过程 1.判断S[next[x]+1]==S[j]
-
如果上步看不懂可以视为,我将S[j]盖在S[x+1]上顶替S[x+1]来求一下next[j],求完next后便将S[j]送回原位
-
-