算法理论
1.前缀表概述
前缀表是用来判断当模式串走到与文本串不相等的情况下,模式串指针j往回退多少。
退到哪里代表模式串中不包含该点的字串的最长的相等前后缀的大小。
2.前缀与后缀
1.前缀:包含第一个数但不包含最后一个数的所有子串都为前缀
2.后缀:包含最后一个数但不包含第一个数的所有子串都为后缀
3.最长相等前后缀
求一个模式串的所有字串的最长相等前后缀即为next数组,比如模式串aabaaf,
求从第一个数开始的所有字串的最长相等前后缀的长度。比如:
a:无前后缀,则为0
aa:1 表示此字串的最长相等前后缀为1
aab:0
aaba:1
aabaa :2
aabaaf:0
代码实现
1.next数组的不同实现
比如aabaaf的next数组为【0,1,0,1,2,0】
可以直接把这个当作next数组,也可以整体右移一位、左边补-1,此时当某个数遇到冲突时,直接跳到当前数对应的next数组的值。
2.具体实现
变量 i:代表后缀的末尾
变量 j:代表前缀末尾,并且代表当前字串的最长相等前后缀
初始化:
j=0:开始前缀为第一个数
next[0]:0 ,第一个数无法回退,还是0
i:因为i代表后缀末尾,需要与前缀末尾进行比较,所以i初始为1
a a b a a f
0 1 0 1 2 0
如初始字串为aa,j=0,i=1
前后缀不同的情况
当j指向的值与i不相同时,则j需要回退到它前一个值的next数组,即j=next[j-1],j直到=0时不能回退,则条件为j>0
又因为回退时可能还不相等,需要继续回退,所以需要使用while循环。
前后缀相同的情况
当相同时,j+1 ,因为j代表最长相等前后缀的长度,所以此时j=1,
此时更新next数组在i位置的值为j,即为当前子串的最长相等前后缀,最后i+1,继续循环。
模拟代码:
j=0,next[0]=0,
for(i=1;i<n;i++)
{
while(j>0&&s[i]!=s[j]) j=next[j-1];
if s[i]==s[j] j++;
next[i]=j;
}