目录
1.串的定义(空串、字串、空格串)
1-1:串是由零个或多个字符组成的有限序列。 (限定了元素为字符的线性表)
1-2:空串:含有零个字符。
1-3:子串:串(主串)中任意连续字符组成的子序列
1-4:空格串:由一个或者多个空格组成的串(空格串不是空串)
2.串的各种基本操作
2-1:串的定义存储
定长顺序存储表示 typedef struct { char str[maxSize+1]; // 多出一个'\0'作为结束标记 int length; }Str; | 变长分配存储表示 typedef struct { char *ch; // 指向动态分配存储区首地址的字符指针 int length; // 串长度 }Str; |
2-2:串的赋值操作
int strassign(Str& str, char* ch) {
if (str.ch)
free(str.ch); // 释放原空间
int len = 0; char *c = ch;
while (*c) { // 求ch串的长度
++len;
++c;
}
if (len == 0) { // 如果ch为空串,则直接返回空串
str.ch = nullptr;
str.length = 0;
return 1;
}
else {
str.ch = (char*)malloc(sizeof(char)*(len+1)); // 取len+1是为了多分配一个空间存放'\0'
if (str.ch == null) // 分配失败
return 0;
else {
c = ch;
for (int i = 0; i <= len; ++i, ++c) // 之所以取<=也是为了将'\0'复制过去
str.ch[i] = *c;
str.length = len;
return 1;
}
}
}
2-3:串的长度操作
int strlength(Str str) {
return str.length;
}
2-4:串的比较操作(串排序应用中的核心操作)
int strcompare(Str s1, Str s2) {
for (int i = 0; i < s1.length && i < s2.length; ++i) {
if (s1.ch[i] != s2.ch[i]) return s1.ch[i] - s2.ch[i];
}
return s1.length - s2.length;
}
2-5:串连接操作
int concat(Str &str, Str str1, Str str2) {
if (str.ch) {
free(str.ch); // 释放原空间
str.ch = nullptr;
}
str.ch = (char*)malloc(sizeof(char)*(str1.length+str2.length));
if (str.ch == null)
return 0;
int i = 0;
while (i < str1.length) {
str.ch[i] = str1.ch[i];
++i;
}
int j = 0;
while (j <= str2.length) {
str.ch[i+j] = str2.ch[j]; // 之所以取<=也是为了将'\0'复制过去
++j;
}
str.length = str1.length + str2.length;
return 1;
}
2-6:求子串操作
int substring(Str& substr, Str str, int pos, int len) {
if (pos<0 || pos>=str.length || len<0 || len>str.length-pos) return 0;
if (substr.ch) {
free(substr.ch);
substr.ch = null;
}
if (len == 0) {
substr.ch = null;
substr.length = 0;
return 1;
} else {
substr.ch = (char*)malloc(sizeof(char)*(len+1));
int i = pos; int j = 0;
while (i<pos+len)
substr.ch[j++] = str.ch[i++];
substr.ch[j] = '\0';
substr.length = len;
return 1;
}
}
2-7:串清空操作
int clearstring(Str& str) {
if (str.ch) {
free(str.ch);
str.ch = null;
}
str.length = 0;
return 1;
}
3.串的模式匹配
配合视频食用更佳:https://www.bilibili.com/video/BV1EE411378s?from=search&seid=10131997502735647979
看完上面这个视频以后,再跟着下面这个视频过一遍:https://www.bilibili.com/video/BV1D441147y8?from=search&seid=13404547156312995020
3-1:简单模式匹配
int index(Str str, Str substr) {
int i = 1, j = 1, k = i;
while (i<=str.length && j<=substr) {
if (str.ch[i] == substr[j]) {
++i;
++j;
} else {
j = 1;
i = ++k; // 匹配失败,i从主串的下一位置开始,k中记录了上一次的起始位置
} }
if (j>substr.length)
return k;
else
return 0;
}
3-2:KMP算法
求next数组的代码
void GetNext(char* p,int next[])
{
int pLen = strlen(p);
next[0] = -1;
int k = -1;
int j = 0;
while (j < pLen - 1)
{
//p[k]表示前缀,p[j]表示后缀
if (k == -1 || p[j] == p[k])
{
++k;
++j;
next[j] = k;
}
else
{
k = next[k];
}
}
}
KMP算法
int KMP(char* s, char* p, int next[])
{
int i = 0; int j = 0;
int sLen = strlen(s),pLen = strlen(p);
while (i < sLen && j < pLen)
{//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if (j == -1 || s[i] == p[j])
{
i++;
j++;
}
else {//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
//next[j]即为j所对应的next值
j = next[j];
}
}
if (j == pLen)
return i - j; // 匹配成功,则返回匹配的位置
else
return -1; }
3-3:KMP算法的改进
void GetNextval(char* p, int next[])
{
int pLen = strlen(p);
next[0] = -1;
int k = -1;
int j = 0;
while (j < pLen - 1)
{ //p[k]表示前缀,p[j]表示后缀
if (k == -1 || p[j] == p[k])
{
++j;
++k;
if (p[j] != p[k])//较之前next数组求法,改动在下面4行
next[j] = k; //之前只有这一行
else { //因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] = next[next[k]]
next[j] = next[k]; }else {
k = next[k];
} } }