【单选】字符串 S = "ababaabab",其所有既是真前缀又是真后缀的子串(非空)的长度之和是( )。
逐一比较 S 的前缀与后缀,找出所有既是真前缀又是真后缀(且非空)的子串:长度 2 的 "ab" 与长度 4 的 "abab",长度和为 6。也可以用 KMP 的 next 数组沿失败链跳。
把 "ababaabab" 本身(长度 9)也算进"真前缀/真后缀"(真 = 不比原串长);或者漏掉较短的 "ab"。
本题考查字符串的前后缀(border)识别,也是 KMP 算法 next 数组的直接应用。
"既是真前缀又是真后缀的非空子串"称为 border(真前缀/真后缀 = 不等于原串本身)。
S = ababaabab(长度 9)
| 长度 | 作为前缀 | 作为后缀 | 是否相同 |
|---|---|---|---|
| 1 | a | b | ✗ |
| 2 | ab | ab | ✓ |
| 3 | aba | bab | ✗ |
| 4 | abab | abab | ✓ |
| 5 | ababa | aabab | ✗ |
| 6 | ababaa | baabab | ✗ |
| 7 | ababaab | abaabab | ✗ |
| 8 | ababaaba | babaabab | ✗ |
| 9 | 原串本身 | — | 不算(非"真") |
满足条件的长度是 2 和 4,长度之和 = 2 + 4 = 6,选 B。
计算 S 的前缀函数 π(π[i] 表示前 i 个字符的最长 border 长度):
| i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| 字符 | a | b | a | b | a | a | b | a | b |
| π[i] | 0 | 0 | 1 | 2 | 3 | 1 | 2 | 3 | 4 |
π[9] = 4 → 最长 border 是 abab(长度 4); 再沿失败链跳:π[4] = 2 → 下一个 border 是 ab(长度 2); π[2] = 0 → 结束。
所有 border 长度:4, 2 → 和为 6 ✓
aba、ababa 之类误判为 border(它们作为后缀时并不相同)。