文章目录
1 串类型的定义
1.1 串
串(string)(或字符串)是由零个或多个字符组成的有限序列,一般记为
s = ′ a 1 a 2 ⋯ a n ′ ( n ≥ 0 ) s = 'a_1 a_2 \cdots a_n ' (n \ge 0) s=′a1a2⋯an′(n≥0)
其中,s是串的名,用单引号括起来的字符序列是串的值
a i ( 1 ≤ i ≤ n ) a_i(1 \le i \le n) ai(1≤i≤n)可以是字母、数字或其他字符
1.2 长度
串中字符的数目 n n n称为串的长度
1.3 空串
零个字符的串称为空串(null string),它的长度为零。
1.4 子串
串中任意个连续字符组成的子序列称为该串的子串。
1.5 主串
包含子串的串相应地称为主串。
1.6 位置
通常称字符在序列中的序号为在串中的位置。
子串在主串中的位置则以子串的第一个字符在主串中的位置来表示
1.7 相等
称两个串是相等的,当且仅当这两个串的值相等。
也就是说,只有当两个串的长度相等,并且各个对应位置的字符都相等时才相等。
2 串的表示和实现
2.1 定长顺序存储表示
用一组地址连续的存储单元存储串值的字符序列
2.2 堆分配存储表示
仍以一组地址连续的存储单元存储串值的字符序列,但它们的存储空间是在程序执行过程中动态分配而得。
2.3 串的块链存储表示
2.4 存储密度
存 储 密 度 = 串 值 所 占 的 存 储 位 实 际 分 配 的 存 储 位 存储密度 = \frac{串值所占的存储位}{实际分配的存储位} 存储密度=实际分配的存储位串值所占的存储位
3 串的模式匹配算法
3.1 求子串位置的定位函数 Index(S, T, pos)
3.1.1 模式匹配
子串的定位操作通常称作串的模式匹配(其中T称为模式串)
3.1.2 BF算法
3.1.2.1 算法描述
将主串的第pos个字符和模式的第一个字符比较,
-
若相等,继续逐个比较后续字符;
-
若不等,从主串的下一字符起,重新与模式的第一个字符比较。
直到主串的一个连续子串字符序列与模式相等 。返回值为S中与T匹配的子序列第一个字符的序号,即匹配成功。
否则,匹配失败,返回值 0
3.1.2.2 时间复杂度
若n为主串长度,m为子串长度,最坏情况是
主串前面n-m个位置都部分匹配到子串的最后一位,即这n-m位各比较了m次
最后m位也各比较了1次
总次数为: ( n − m ) ∗ m + m = ( n − m + 1 ) ∗ m (n-m)*m+m=(n-m+1)*m (n−m)∗m+m=(n−m+1)∗m
若 m < < n m<<n m<<n,则算法复杂度 O ( n ∗ m ) O(n*m) O(n∗m)
3.2 模式匹配的一种改进算法(KMP算法)
3.2.1 时间复杂度
此算法可以在 O ( n + m ) O(n + m) O(n+m)的时间数量级上完成串的模式匹配操作。
3.2.2 改进之处
每当一趟匹配过程中出现字符串比较不等时,不需回溯i指针
而是利用已经得到的“部分匹配”的结果,将模式串向右“滑动”尽可能远的一段距离后,继续进行比较
3.2.3 代码实现
const int maxn = 1e6 + 10;
int nxt[maxn];
char s1[maxn], s2[maxn];
int len1, len2;
void get_next(){
int i = 0, j = -1;
nxt[0] = -1;
while(i < len2) {
if(j == -1 || s2[i] == s2[j]) {
i++;
j++;
nxt[i] = j;
}else
j = nxt[j];
}
return ;
}
void kmp() {
int i = 0, j = 0;
get_next();
while(i < len1){
if(j == -1 || s1[i] == s2[j]) {
++i;
++j;
}else
j = nxt[j];
if(j == len2){ //成功匹配 i为主串下标 j为模式串下标
pd(i - len2);
j = nxt[j];
}
}
}