字符串与栈
1. 字符串
字符串是数算 B 中较难的内容之一,涉及 KMP 算法、动态规划等。
字符串在内存中主要以顺序表(字符数组)形式存储,也可以用链表存储。字符串以 \0 作为结束标记,对应 ASCII 编码为 0,而不是字符 '0'。
字符型变量与 ASCII
int main(){
char b, c, d;
b = 'x';
c = b;
d = 120; // 也对应 ASCII 中的 'x'
}
'A'的 ASCII 码小于'a',相差 20。- 实际编码可能用 2 个或 4 个字节表示一个字符。
模式匹配
模式匹配的目标是在主串中找到子串(模式串)首次出现的位置,通常返回指针或下标。
朴素模式匹配(回溯)
主串:a b a b c a b c d
模式:a b c
每次匹配失败,模式串向右移动一位,主串指针回退。
时间复杂度:
其中
KMP 算法
KMP 算法通过预处理模式串,避免主串指针回退。
核心概念:next 数组,表示模式串每个位置之前的最长相同前后缀长度。
时间复杂度:
:构造 next 数组。 :匹配过程。
考试中常见题型:根据给定模式串手写 next 数组。
#include <vector>
vector<int> a(10000); // 预先指定长度可减少内存碎片
2. 栈
定义
栈(Stack)是一种后进先出(Last In First Out, LIFO)的线性表,只允许在一端(栈顶)进行插入和删除。
基本操作:
push():入栈pop():出栈top():查看栈顶元素
实现形式
- 顺序栈:使用更多,基于数组实现。
- 链式栈:栈顶在链表头部,新插入的元素指向旧栈顶。
链式栈出栈时要记得释放节点,否则会造成内存泄漏:
Node* q = top;
top = top->next;
delete q;
栈的应用
- 进制转换:先得到低位,最后输出,天然适合栈。
- 括号匹配:左括号入栈,右括号与栈顶匹配。
- 表达式求值:中缀转后缀、后缀表达式求值。
- 递归实现:递归调用栈本质上就是系统维护的栈。
关键提醒
要仔细阅读函数声明,理解到底是在修改引用,还是创建了新的局部变量。
有时候,使用功能受限的数据结构(如栈、队列)反而更适合解决算法题。
3. 队列(补充)
队列是先进先出(First In First Out, FIFO)的线性表:
- 在队尾入队
enqueue()。 - 在队头出队
dequeue()。
常见应用:
- BFS(广度优先搜索)
- 缓冲区 / 任务调度
4. 小结
| 结构 | 核心特征 | 经典应用 |
|---|---|---|
| 字符串 | 字符序列 | 模式匹配、文本处理 |
| 栈 | LIFO | 括号匹配、表达式求值、递归 |
| 队列 | FIFO | BFS、缓冲区 |
KMP 的 next 数组、栈的 LIFO 性质是笔试和上机都常考的重点。