若比较到 T[6] 时失配,说明 T[1..5] = abaab 已经匹配。
abaab。已知:T[1..5] 已匹配 目标:找到 T[6] 失配后,j 应回退到哪个位置继续比较
前缀长度 4取 T[1..4]
后缀长度 4取 T[2..5]
abaa != baab,不能保留 4 个已匹配字符,继续后退。若 next[6] = 5,则表示下一次用 T[5] 比较; 这要求已匹配段中长度为 4 的前缀和后缀相同,但这里不成立。
前缀长度 3取 T[1..3]
后缀长度 3取 T[3..5]
aba != aab,不能保留 3 个已匹配字符,继续后退。若 next[6] = 4,则下一次用 T[4] 比较; 这要求长度为 3 的前缀和后缀相同,但这里不成立。
前缀长度 2取 T[1..2]
后缀长度 2取 T[4..5]
ab == ab,可以保留 2 个已匹配字符。所以下一次从 T[3] 继续比较。保留字符数 = 2 下一次比较位置 = 保留字符数 + 1 = 3 所以 next[6] = 3
后退后,模式串开头的 ab 与主串中已匹配段末尾的 ab 对齐。当前主串字符仍是刚才让 T[6] 失配的字符。
T[3] 和当前 S[i] 比较。next[6] = 3 表示:当 T[6] 失配,并且 T[1..5] 已匹配时,模式串指针 j 回退到 3。
if (S.ch[i] == T.ch[j]) {
++i; // 当前字符匹配,主串继续看下一个字符
++j; // 模式串也继续看下一个字符
} else {
// T[6] 失配时,T[1..5] 已经匹配。
// next[6] = 3 表示保留前后能对齐的 "ab",
// 下一次用 T[3] 和当前 S[i] 比较,主串指针 i 不动。
j = next[j];
}
i 不回退;被保留下来的 ab 不需要重新比较。手算时不要直接背表。对每个 j,都把分界线画在 T[j] 前面,只看 T[1..j-1],再从最长可保留部分开始逐步后退。