4. 串
字符串的定义、存储和操作
定义
- 串:是由零个或多个字符组成的有序序列,一般记为 s = ’\(a_1a_2\cdots a_n\)‘
- 长度:串中字符数目 \(n\) 称为串的长度
- 空串:零个字符的串称为空串
- 子串:串中任意个连续的字符组成的子序列称为该串的子串
- 主串:包含子串的串称为主串
- 位置:字符在序列中的序号
- 相等:当且仅当两个串值相等(长度相等,对应位置的元素值相等)
存储与操作
1 | // 算法 4.1 |
定长顺序存储表示
- 存储
1 | // 串的定长顺序表示 |
- 操作
1 | // 算法 4.2 |
1 | // 算法 4.3 |
堆分配存储表示
- 存储
1 | // 串的堆分配存储表示 |
- 操作
1 | // 算法 4.4 |
- 以下为基本操作(最小操作子集)
1 | // 串的新建赋值 |
1 | // 串的长度 |
1 | // 串的比较( 实现巧妙 ) |
1 | // 串的清空 |
1 | // 串的联接 |
1 | // 求串的子串 |
块链存储表示
- 存储
1 | // 串的块链存储表示 |
- 操作(与线性表相关操作类似)
字符串的模式匹配(★)
(下面均以顺序存储结构为例)
原始算法
1 | // 算法 4.5 |
KMP 算法
匹配算法
1 | // 算法 4.6 |
计算 next 数组
1 | // 算法 4.7 |
1 | // 算法 4.8 |
补充:一种手算 next 数组的方法
教材写的太难懂了,这里分享一下王道中的方法。
先理清几个概念:
- 前缀:除最后一个字符,字符串的所有头部子串
- 后缀:除第一个字符,字符串的所有尾部子串
- 部分匹配值:字符串的前缀和后缀的最长相等前后缀长度
举个例子:计算 ‘ababa’ 的 next 数组
- 先算部分匹配值
子串 | 前缀 | 后缀 | 前后缀交集 | 最长相等前后缀长度 |
---|---|---|---|---|
'a' | \(\varnothing\) | \(\varnothing\) | \(\varnothing\) | 0 |
'ab' | {'a'} | {'b'} | \(\varnothing\) | 0 |
'aba' | {'a', 'ab'} | {'ba', 'a'} | {'a'} | 1(= len('a')) |
'abab' | {'a', 'ab', 'aba'} | {'bab', 'ab', 'b'} | {'ab'} | 2(= len('ab')) |
'ababa' | {'a', 'ab', 'aba', 'abab'} | {'baba', 'aba', 'ba',' a'} | {'a', 'aba'} | 3(= len('aba')) |
故部分匹配值为 00123
- 再算 next 数组
next 数组为上述匹配值先右移(左边补 -1),再每位加 1
此例便为
- 右移:
-10012
(注:若位序从 0 开始,取这个答案) - 每位加一:
01123
(注:若位序从 1 开始,取这个答案)
故此例 next 数组为 01123
参考资料
- 数据结构(C语言版).严蔚敏
- 2020年数据结构考研复习指导.王道论坛