算法专题样片

KMP:为什么 i 不回退

这一页用浏览器端生成的执行 trace 串起代码分支、指针移动、边界条件和最终返回值。

当前视频
交互样片

不用加载视频文件,直接逐步查看代码、内存、栈帧和 CPU 阶段。

HTML 交互动画
浏览器端生成 KMP 执行过程

不加载视频文件,直接用结构化 trace 渲染代码行、内存方格、CPU 阶段和栈帧状态。

kmp.go
代码执行轨迹
完整 strStr 函数。高亮行就是当前程序计数器所在位置。
1
func strStr(haystack, needle string) int {// 入口函数
2
n := len(haystack)// 文本长度
3
m := len(needle)// 模式长度
4
if m == 0 { return 0 }// 空模式
5
if n < m { return -1 }// 长度不够
6
lps := buildLPS(needle)// 先做记忆表
7
PC8
i, j := 0, 0// 两个指针
9
for i < n {// i 只向右
10
if haystack[i] == needle[j] {// 当前相等
11
i++
12
j++// 一起前进
13
} else if j > 0 {// 已有匹配
14
j = lps[j-1]// i 不动
15
} else {
16
i++// 没有记忆
17
}
18
if j == m { return i-j }// 返回起点
19
}
20
return -1// 没有找到
21
}
内存
haystack
i
a
0
b
1
a
2
b
3
c
4
a
5
b
6
c
7
a
8
c
9
b
10
a
11
b
12
needle
j
a
0
b
1
c
2
a
3
c
4
lps
0
0
0
1
0
2
1
3
0
4
抽象 CPU
LOAD
BRANCH
WRITE
compare-
branch准备进入循环
调用栈
strStr 栈帧
FP 0x7ff0
SP 0x7fb8
地址槽位
0x7ff8控制返回地址caller+pc
0x7ff0控制保存 FP0x8010
0x7fe8参数haystack*heap[H]
0x7fe0参数needle*heap[N]
0x7fd8局部变量n13
0x7fd0局部变量m5
0x7fc8局部变量lps*heap[L]
0x7fc0局部变量i0
0x7fb8局部变量j0
只读
初始化栈帧

抽象计算机先在栈帧里放入 i、j、n、m。

Step 1 / 1010%

视频 fallback

HTML 播放器验证期间,保留已渲染 MP4 版本作为回退。

第 2 集

代码执行流程

代码行、i/j 指针移动、lps 回退和 return i-j。

第 3 集

抽象机执行流程

PC、栈帧、内存读取、分支判断和变量写回。

边界条件

为什么空 needle 返回 0,为什么 needle 更长时直接返回 -1。

buildLPS 状态

看 i、length、lps 如何在 needle 自己内部变化。

匹配分支

理解为什么 j 根据 lps 回退,而 haystack 的 i 保持不动。

如何放进 5tldr

Step 1

把生成好的视频作为版本化静态资源放在 public/learning 下。

Step 2

每个概念一页:视频、要点、文字稿、练习入口放在同一专题页。

Step 3

样片阶段先 noindex,等形式稳定后再从 Resources 或 Learning Plans 挂入口。

KMP 算法代码执行可视化 | 5tldr | 5tldr