注:本文后续持续更新,如有问题欢迎指正。如果有函数需要添加,欢迎留言。
字符串学习
1. 相关库函数
#include <string.h>
函数名 | 说明 | 详细学习网址 |
---|---|---|
strcpy | 字符串复制 | 详情 |
strncpy | 字符串部分复制 | 详情 |
strcat | 字符串连接 | |
strncat | 特定数量的字符串连接到另一个字符串 | |
_strdup | 预先配置内存,将字符串存入该内存中 | |
strchr | 给定字符串中搜寻指定字符串 | |
strcspn | 给定字符串中搜寻某个指定字符串第一次出现的位置 | |
strrchr | 给定字符串中搜寻某个指定字符最后一次出现的地址 | |
strpbrk | 两个字符串中寻找首次共同出现的字符 | |
strstr | 两个字符串中寻找首次共同出现的公共子字符串 | |
strlen | 计算字符串长度 | |
_strnset | 给定的字符串中按指定书目将若干字符置换为指定字符 | |
strcmp | 字符串比较大小 |
2. 字符串的实现
3. 字符串的模式匹配
问题描述
- 在目标串中查找模式串
方法一:B-F算法(由两位提出者的名字首写字母构成)
描述
- 思想: 用模式串的字符一次与目标串中的字符作比较,直到匹配成功或者目标串必配完成
- 该算法是一种带回溯的算法
- 运行时间为O(m*n)
实现
//str:目标串 dest:模式串 begin:目标串开始查找位置 str_size: 目标串长度 dest_size:模式串长度
//返回值:模式串在目标串中匹配的起始位置
int find(char* str, int begin, int str_size, char* dest, int dest_size) {
for (int i=begin; i<str_size; i++) {
int j;
for (j=0; j<dest_size && str[i+j] == dest[j]; j++) ;
if (j == dest_size)
return i;
}
return -1;
}
方法二:KMP(以提出人名字首字母命名)
描述
- 该算法主要消除没有必要的回溯,从模式串入手
- 该算法可以消除回溯
- 时间复杂度O(m+n)
求解过程
- 设目标
T="t0, t1....tn-1"
, 模式串P =p0, p1....pm-1
- 假设在第s趟比较时,在
T
的s+j
位置失配,有ts = p0
,ts+1 = p1
,...
,ts+j-1 = pj-1
,ts+j != pj
*如果按照B-F算法,下一趟从目标串的s+1位置开始重新匹配,如果想要匹配,必须满足\
p0p1p2...pj-1...pm-1 = ts+1ts+2ts+3...ts+j...ts+m
- 如果上式不能满足就会失配,如果提前可以知道就可以避免不必要的回溯,直接从
k
位置开始匹配,其中k
满足 \
p0p1...pk = pj-k-1pj-k..pj-1
, 这样就可以直接从T串s+j位置重现开始匹配 - 关于
k
值的确定只依赖模式串,与目标串无关,因此可以用一个next特征函数来确定 - 设定当j=0时,next[j] = 0
实现
//求解next, 时间复杂度为O(size)
void getNext(int next[], int size) {
next[0] = -1;
int j=0, k=-1;
while (j < size-1) {
if (k == -1 || next[k] == next[j]) {
k++;
j++;
next[j] = k;
} else {
next[j] = k;
}
}
}
int KMP(char p[], char s[], int size_p, int size_s) {
int i=0;
for( int j=0; j<size_p; j++) {
if (p[i] != s[j]) {
}
}