目录
一、串的定义
1.1概念
串是零个或多个任意字符组成的有限序列
1.2相关术语
①子串:串中任意个连续字符组成的子序列
②主串:包含子串的串
③字符位置:字符在序列中的序号
④子串位置:子串第一个字符在主串中的位置
⑤空格串:由一个或多个空格组成的串,与空串不同
例:字符串a、b、c、d
a='BEI'
b='JING'
c='BEIJING'
d='BEI JING'
它们的长度是:3、4、7、8
c的子串是:a、b
d的子串是:a、b
a在c中的位置是:1;a在d中的位置是:1
b在c中的位置是:4;b在d中的位置是:5
·串相等:当且仅当两个串的长度相等并且各个位置上的字符都相同时,这两个串才相等。
例:“abcd”≠“abc” 、“abcd”≠“abcde”
(所有空串是相等的)
1.3串的类型定义
ADT String{
数据对象:D={ai | ai∈CharacterSet,i=1,2,3,....,n,n>=0}
数据关系:R1={<a(i-1),ai> | a(i-1),ai∈D,i=1,2,....,n}
基本操作:
①StrAssign (&T,chars) //串赋值
②StrCompare (S,T) //串比较
③StrLength (S) //求串长
④Concat (&T,S1,S2) //串连结
⑤SubString (&Sub,S,pos,len) //求子串
⑥StrCopy (&T,S) //串拷贝
⑦StrEmpty (S) //串判空
⑧ClearString (&S) //清空串
⑨Index (S,T,pos) //子串的位置
⑩Replace (&S,T,V) //串替换
11.StrInsert ($S,pos,T) //子串插入
12.StrDelete (&S,pos,len) //子串删除
13. DestroyString (&S) //串销毁
}ADT String
二、串的存储结构
2.1串的顺序存储结构
#define MAXLEN 255 [0]~[255] 一般从[1]开始
typedef struct{
char ch[MAXLEN+1]; //存储串的一维数组
int length; //串的当前长度
}SString;
2.2串的链式存储结构——块链结构
#define CHUNKSIZE 80 //块的大小可由用户定义
typedef struct Chunk;{
char ch[CHUNKSIZE];
struct CHUNK *next;
}Chunk;
typedef struct{
Chunk *head,*tail; //串的头指针和尾指针
int curlen; //串的当前长度
}LString; //字符串的块链结构
三、串的模式匹配算法
3.1BF算法
·算法思路:
从S的每一个字符开始依次与T的字符进行匹配
·算法步骤:
①分别利用计数指针i和j指示主串S和模式T中当前正待比较的字符位置,i初值为pos,j初值为1.
②如果两个串均未比较到串尾,即i和j均分别小于等于S和T的长度时,则循环执行以下操作:
·S.ch[i] 和 T.ch[j] 比较,若相等,则i和j分别指示串中下个位置,继续比较后续字符;若不等,指针后退重新开始匹配,从主串的下一个字符(i=i-j+2)起再重新和模式的第一个字符(j=1)比较
③如果j>T.length ,说明模式T中的每个字符依次和主串S中的一个连续的字符序列相等,则匹配成功,返回和模式T中第一个字符相等的字符在主串S中的序号(i-T.length);否则匹配失败,返回0
·算法描述
int Index_BF(SString S,SString T,int pos){
//返回模式T在主串S中第pos个字符开始第一次出现的位置,若不存在,则返回0
//其中,T非空,1<=pop<=S.length
int i=pos;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; //匹配失败
·算法分析
①最好情况下的平均时间复杂度为O(n+m)
②最坏情况下的平均时间复杂度为O(n*m)
3.2KMP算法
·算法描述
int Index_KMP(SString S, SString T, int pos)
{//利用模式串T的next函数求T在主串S中第pos个字符之后的位置
//其中,T非空,1<=pos<=S.length
i=pos;j=1;
while(i<=S.length && j<=T.length){ //两个串均未比较到串尾
if(j==0 || S.ch[i]==T.ch[j]) {++i;++j;} //继续比较后继字符
else j=next[j]; //模式串向右移动
}
if(j>T.length) return i-T.length; //匹配成功
else return 0; //匹配失败
关于计算next函数值的算法描述
void get_next(SString T,int next[]){
//求模式串T的next函数值并将其存入数组next
i=1;next[1]=0;j=0;
while(i<T.length){
if(j==0 || T.ch[i]==T.ch[j]) {++i;++j;}
else j=next[j];
}
}
计算next函数修正值的算法描述
void get_nextval(SString T, int nextval[]){
//求模式串T的next函数修正值并将其存入数组nextval
i=1;nextval[1]=0;j=0;
while(i<T.length){
if(j==0 || T.ch[i]==T.ch[j])
{
++i;++j;
if(T.ch[i]!=T.ch[j]) nextval[i]=j;
else nextval[i]=nextval[j];
}
else j=nextval[j];
}
}