现代 C++ 实战(23):字符串搜索与动态规划
第 22 篇 的图算法处理「关系」;本篇进入算法面试的两大支柱:字符串搜索(在文本中找模式)和动态规划(把大问题拆成重叠子问题)。KMP 和 Boyer-Moore 解决搜索,背包和 LCS 解决 DP——掌握这些,LeetCode 中等题大半有思路。 demo:ref/cpp_demo/algorithms/string_search/ + ref/cpp_demo/algorithms/dynamic_programming/。 这是「现代 C++ 实战」系列的第 23 篇。建议先读 第 22 篇:图算法。 一、字符串搜索全景在文本 text(长度 n)中查找模式 pattern(长度 m): 算法 时间 思路 适用 暴力 O(nm) 每个位置逐字符比 短模式、教学 KMP O(n+m) 前缀函数,失配不回退 text 通用、面试必考 Boyer-Moore 最好 O(n/m) 从右向左,坏字符跳跃 长模式、实际文本搜索 Rabin-Karp 平均 O(n+m) 滚动哈希,先比哈希再验证 多模式匹配 1234text: A ...
x86 汇编入门(05):函数调用与递归阶乘
call 和 ret 是汇编里最重要的「接力棒」。没有它们,代码只能从上到下一条道走到黑。这一篇我们拆开函数调用的完整机制,并用递归计算 5 的阶乘——在汇编里亲眼看到栈是怎么一层层长高的。 这是「x86 汇编入门」系列的第 5 篇。上一篇用跳转实现了循环。这一篇通过 05_function.asm,理解 call / ret、栈帧和 x86_64 调用约定。 一、call 和 ret 做了什么?123call factorial ; ① 把「下一条指令地址」压栈 ② 跳到 factorial...ret ; 从栈弹出地址,跳回去 可以把它想成:call 留下回城坐标,ret 按坐标回去。栈就是存放这些坐标的地方。 二、栈帧:函数自己的「工作台」每次进入函数,标准开场是: 12345678factorial: push rbp ; 保存调用者的帧指针 mov rbp, rsp ; 建立当前帧 push rbx ; 保存要用的 callee...
大模型数学速成(08):ViT 层 vs LLM 层——概念对照总表
前 7 篇我们分别讲了张量约定、矩阵乘、Q/K/V、Norm 与残差、Attention、FFN、RoPE—— pieces 齐了,但读 ViT 或 LLM 代码时仍容易混:patch 和 token 是一回事吗?为什么 ViT 双向、LLM 因果?RMS Norm 和 LayerNorm 谁在哪? 这一篇不引入新公式,用 一张骨架图 + 对照大表 把视觉 Transformer 与语言模型在同一套数学语言下对齐,并给出后续阅读路径。 这是「大模型数学速成」系列的第 8 篇。建议已读 第 00–07 篇。下一篇 多头注意力。 一、共同的 Transformer 骨架无论 ViT 还是 LLM,一层 block 的核心结构相同(Pre-LN 写法): 12345678输入 X [d, S] S = 序列长度(patch 数或 token 数) │ ├─ Norm ──► Self-Attention ──► + 残差 │ ├─ Norm ──► FFN ──► + 残差 │ ▼输出 X' [d, S...
现代 C++ 实战(22):图算法
第 21 篇 的树是一对多分支;图则允许任意顶点之间连边——社交网络、路由表、任务依赖、编译单元关系,本质都是图。BFS 找最短、DFS 探路径、Dijkstra 算权重、拓扑排序排依赖——四大经典算法覆盖 90% 的工程场景。 demo:ref/cpp_demo/algorithms/graph/(graph.h、bfs、dfs、dijkstra、topological_sort)。 这是「现代 C++ 实战」系列的第 22 篇。建议先读 第 21 篇:树结构全家桶。 一、图的两种表示顶点 V、边 E。两种存储方式,时空权衡不同: 表示 空间 查边 遍历邻居 适用 邻接矩阵 O(V²) O(1) O(V) 稠密图、频繁查边 邻接表 O(V+E) O(度) O(度) 稀疏图、遍历为主 123456邻接矩阵(6 顶点) 邻接表 0 1 2 3 4 5 0 → [1, 2]0 [ 0 1 1 0 0 0 ] 1 → [3]1 [ 0 0 0 1 0 0 ] 2 → [...
x86 汇编入门(04):循环与条件跳转
高级语言里写 for (i = 1; i <= 10; i++) 一行搞定。汇编里没有 for,只有比较 + 跳转。这一篇用 04_loop.asm 打印 1 到 10,把循环拆成你能看见的每一步。 这是「x86 汇编入门」系列的第 4 篇。上一篇实现了算术和数字打印。这一篇通过 04_loop.asm,学习条件跳转指令和循环结构的汇编写法。 一、比较与跳转cmp a, b 做减法但不保存结果,只设置 CPU 标志位。然后根据标志位跳转: 指令 条件 je 相等 (ZF=1) jne 不相等 jl 小于(有符号) jle 小于等于 jg 大于 jge 大于等于 jmp 无条件跳转 二、用跳转拼出循环04_loop.asm 的逻辑等价于: 123for (int i = 1; i <= 10; i++) { printf("当前数字: %d\n", i);} 汇编实现: 1234567891011121314mov r12, 1 ...
大模型数学速成(07):RoPE——用旋转编码位置
Self-Attention 本身不包含位置信息——打乱 token 顺序,只要 Q/K/V 一起打乱,注意力分数不变。但语言有语序:「狗咬人」≠「人咬狗」。位置编码告诉模型每个 token 在序列中的位置;现代 LLM 广泛使用的 RoPE(Rotary Position Embedding,旋转位置编码) 通过「旋转」Q/K 向量来注入相对位置。 这一篇搞懂:为什么需要 RoPE、旋转在算什么、为何只改 Q/K、以及绝对位置与相对位置的关系。 这是「大模型数学速成」系列的第 7 篇。建议先读 第 06 篇:FFN。下一篇 ViT 层 vs LLM 层对照总表。 一、顺序问题:Attention 是「置换等变」的第 05 篇 的注意力只看点积相似度。若把 token 列整体重排(Q、K、V 同步重排),每个 token 关注谁不变——模型不知道谁在前谁在后。 早期做法: 方法 思路 代表 绝对位置嵌入 给每个位置 $i$ 学一个向量 $p_i$,$x + p_i$ 原始 Transformer RoPE 按位置旋转...
现代 C++ 实战(21):树结构全家桶
第 20 篇 的链表是「一对一」串联;树则是一对多的分支结构。从二叉搜索树到 AVL、红黑树、B 树、堆——五种经典树形结构,覆盖了内存索引、STL 容器、优先队列和磁盘存储的核心场景。 demo:ref/cpp_demo/algorithms/tree/(binary_tree、avl_tree、red_black_tree、b_tree、heap)。 这是「现代 C++ 实战」系列的第 21 篇。建议先读 第 20 篇:栈、队列与链表。 一、五种树,一张选型地图 结构 平衡策略 查找 插入 典型场景 BST 无保证 O(h) O(h) 教学、小规模有序数据 AVL 严格平衡 O(log n) O(log n) 查找密集、更新较少 红黑树 近似平衡 O(log n) O(log n) std::map / std::set B 树 多路平衡 O(log n) O(log n) 数据库索引、文件系统 堆 堆序性质 O(n) 查任意 O(log n) 优先队列、Top-K 12345678910111213BST(可能退化成链) ...
x86 汇编入门(03):算术运算与数字转字符串
终端只能显示字符,不能直接显示数字 42。所以汇编里做算术只是第一步,更麻烦的是把结果「翻译」成 '4' 和 '2' 再送出去。这一篇我们练四则运算,并实现一个可复用的 print_number 子程序。 这是「x86 汇编入门」系列的第 3 篇。前两篇解决了输出字符串和读取输入。这一篇通过 03_calc.asm,掌握算术指令和整数转 ASCII 的核心技巧。 一、基本算术指令对两个常数 42 和 8 演示四则运算: 指令 含义 示例结果 add dst, src 加法 42 + 8 = 50 sub dst, src 减法 42 - 8 = 34 imul dst, src 有符号乘法 42 × 8 = 336 idiv src 有符号除法 42 ÷ 8 = 5 … 2 除法要特别注意:idiv 用 rdx:rax 作为被除数。执行前需要 cqo 把 rax 符号扩展到 rdx: 1234mov rax, num_acqo ...
大模型数学速成(06):前馈网络 FFN——GELU 与 SwiGLU
上一篇里,每个 token 通过注意力「看过」其他 token。但注意力只做加权混合——线性组合 V,表达能力有限。Transformer 块的另一半是 FFN(Feed-Forward Network,前馈网络):对每个 token 独立做「升维 → 非线性 → 降维」,注入更强的逐 token 变换能力。 这一篇搞懂 FFN 在算什么、GELU / SwiGLU 是什么、以及 ViT 与 LLM 的常见差异。 这是「大模型数学速成」系列的第 6 篇。建议先读 第 05 篇:注意力与 Softmax。下一篇讲 RoPE 位置编码。 一、注意力 vs FFN:分工不同 Self-Attention FFN 跨 token ✅ token 之间交换信息 ❌ 每个 token 独立处理 主要操作 加权求和(线性) 矩阵乘 + 非线性激活 类比 开会对齐信息 会后各自消化、深度加工 形状 [d, S] → [d, S] [d, S] → [d, S] 完整 Transformer 子层(Pre-LN)典型顺序: 1x → Norm → At...
现代 C++ 实战(20):栈、队列与链表
第 19 篇 的哈希表用数组 + 指针组织数据;再往前退一步,有三种几乎无处不在的基础结构:栈(LIFO)、队列(FIFO)、链表(动态串联节点)。实现简单,却是表达式求值、BFS、LRU 的底座。 demo:ref/cpp_demo/algorithms/stack_queue_list/(stack_demo、queue_demo、linked_list_demo)。 这是「现代 C++ 实战」系列的第 20 篇。建议先读 第 19 篇:哈希表。 一、三种结构一句话 结构 规则 典型操作 栈 Stack 后进先出 LIFO push / pop / top 队列 Queue 先进先出 FIFO enqueue / dequeue / front 链表 Linked List 节点 + 指针串联 头插、尾插、删除、遍历 12栈: push → [30][20][10] ← top 队列: front → [10][20][30] ← back链表: head → (30) → (20) → (10)...















