串的基本定义
串(String):零个或多个任意字符组成的有限序列
几个术语
-
子串:一个串中任意个连续字符组成的子序列(含空串)称为该串的子串
-
例如 “abcde”的字串
-
“” 、“a”、“abc”、“abcd” 等
-
-
-
真子串:是指不包含自身的所有子串。
-
主串:包含子串的串相应地称为主串。
-
字符位置:字符在序列中的序号为该字符在串中的位置 。
-
子串位置:子串第一个字符在主串中的位置。
-
空格串:由一个或者多个空格组成的串 与空串不同
-
串相等:当且仅当两个串的长度相等并且各自对应位置上的字符都相等,这两个串才是相等的。
-
所有的空串是相等的。
串的类型定义、存储结构及运算
-
StrAssign(&T, chars)
-
初始条件:chars是字符串常址。
-
操作结果:生成 一个其值等于chars的串T。
-
-
StrCopy(&T,S)
-
初始条件:串s存在。
-
操作结果:由串s复制得串T。
-
-
StrEmpty(S)
-
初始条件:串s存在。
-
操作结果:若s为空串,则返回 tr ue, 否则返回false。
-
-
StrCompar e(S,T)
-
初始条件:串 s和T存在。
-
操作结果:若S>T, 则返回值 >0; 若S=T, 则返回值= O; 若S
-
-
Replace(&S,T,V)
-
初始条件:串S, T和V存在, T是非空串。
-
操作结果:用V替换主串s中出现的所有与T相等的不重叠的子串。
-
-
Strlnsert(&S,pos,T)
-
初始条件:串 s和 T 存在,1<=pos<=StrLength(S)+1。
-
操作结果:在串 s 的第 pos 个字符之前插人串 。
-
-
StrDelete(&S,pos,len)
-
初始条件:串 S 存在 ,1<=pos<=StrLength(S)-len+1
-
操作结果:从串 s 中删除第 pos 个字符起长度为 len 的子串。
-
-
DestroyString (&S)
-
初始条件:串s存在。
-
操作结果:串s被销毁。
-
串中元素逻辑关系与线性表的相同,串可以采用与线性表相同的存储结构
串的存储结构
-
串的顺序存储结构
# define MAXLEN 255
typedef struct{
char ch[MAXLEN+1]; // 存储串的一维数组
int length; // 串的当前长度
}SString;
-
串的链式存储结构
# define CHUNKSIZE 80
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk *next;
}CHunk;
typedef struct{
Chunk *head; // 串的头指针
int curlen; // 串的当前长度
Chunk *tail; // 串的尾指针
}LString;
串的模式匹配算法
算法目的
确定主串中所含子串(模式串)第一次出现的位置(定位)
算法应用:
-
搜索引擎、拼写检查、语言翻译、数据压缩
算法种类:
-
BF算法(Brute-Force,又称古典的、经典的、朴素的、穷举的)
-
KMP算法(特点:速度快)
BF算法
Brute-Force 简称BF算法,亦称简单匹配算法。采用穷举法的思路。
Index(S,T,pos)
-
将主串的第pos个字符和模式串的第一个字符比较,
-
若相等,继续逐个比较后续字符;
-
若不等,从主串的下一字符起,重新与模式串的第一个字符比较
-
直到主串的一个连续子串字符序列与模式串相等。返回值为S中与T匹配的子序列第一个字符的序号,即匹配成功。
-
否则,匹配失败,返回值0
# include <stdio.h>
#include <string.h>
# define MAXLEN 255
typedef struct{
char ch[MAXLEN+1]; // 存储串的一维数组
int length; // 串的当前长度
}SString;
// BF算法
int Index_BF(SString S,SString T){
int i = 1;
int j = 1;
while(i<=S.length&&j<=T.length){
if(S.ch[i] == T.ch[j]){ // 主串和子串依次匹配下一个字符
++i;
++j;
}else{
i = i-j+2;
j = 1; // 主串、子串指针回溯重新开始下一次匹配
}
}
if(j>=T.length){
return i-T.length; // 返回匹配的第一个字符的下标
}else{
return 0; // 模式匹配不成功
}
}
int main(){
return 0;
}
KMP算法
算法思路:
KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的,称之为 Knuth-
Morria-Pratt 算法,简称 KMP 算法。该算法相对于 Brute-Force(暴力)算法有比较大的
改进,主要是消除了主串指针的回溯,从而使算法效率有了某种程度的提高。
利用已经部分匹配的结果而加快模式串的滑动速度
且主串S的指针i不必回溯,可提速到O(n+m)
next函数改进
KMP算法的代码思路:
// KMP 算法
int Index_KMP(SString S,SString T,int pos){
int i = pos;
int j = 1;
while( i<=S.length && j<=T.length){
if( S.ch[i] == T.ch[j] || j == 0){
i++;
j++;
}
else{
j = next[j]; /*i不变,j后退*/
}
}
if(j>T.length){
return i-T.length;
}else{
return 0;
}
}
求 next[j] 的方法
// 求 next[j] 的方法
void get_next(SString T,int &next[]){
int i = 1;
int j = 0;
next[1] = 0;
while(i<=T.length){
if(j==0|| T.ch[i] == T.ch[j]){
i++;
j++;
next[i] = j;
}else{
j = next[j];
}
}
}
next 改进:
// next 改进
void get_nextval(SString T,int &nextval[]){
int i = 1;
int j = 0;
nextval[1] = 0;
while(i<T.length){
if(T.ch[i] == T.ch[j]||j==0){
i++;
j++;
if(T.ch[i] != T.ch[j]){
nextval[i] = j;
}
else{
nextval[i] = nextval[j]
}
}
else{
j = nextval[j];
}
}
}