4.1串的基本操作
StrAssign(&T,chars):赋值操作。把串T赋值为chars。
StrCopy(&T,S):复制操作。由串S复制得到串T。
StrEmpty(S):判空操作。若S为空串,则返回TRUE,否则返回FALSE。
StrLength(S):求串长。返回串S的元素个数。
ClearString(&S):清空操作。将S清为空串。
DestroyString(&S):销毁串。将串S销毁(回收存储空间)。
Concat(&T,S1,S2):串联接。用T返回由S1和S2联接而成的新串
SubString(&Sub,S,pos,len):求子串。用Sub返回串S的第pos个字符起长度为len的子串。
Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0。
StrCompare(S,T):比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
串的存储结构
顺序存储
系统自动回收内存空间
#define MAXLEN 255 //预定义最大串长为255
typedef struct{
char ch[MAXLEN]; //每个分量存储一个字符 静态数组实现(定长顺序存储)
int length; //串的实际长度
}SString;
需要手动回收内存空间
typedef struct{
char *ch; //按串长分配存储区,ch指向串的基地址
int length; //串的长度
}HString; //动态数组实现(堆分配存储)
HString S;
S.ch = (char *) malloc(MAXLEN *sizeof(char));
S.length = 0;
链式存储
typedef struct StringNodef{
char ch; //每个结点存1个字符
struct StringNode * next;
}StringNode,* String;
typedef struct StringNodef{
char ch[4]; //每个结点存多个字符
struct StringNode * next;
}StringNode,* String; //存储密度高
基于顺序存储实现基本操作
SubString(&Sub,S,pos,len):求子串。用Sub返回串S的第pos个字符起长度为len的子串。
#define MAXLEN 255 //预定义最大串长为255
typedef struct{
char ch[MAXLEN]; //每个分量存储一个字符
int length; //串的实际长度
}SString;
//求子串
bool SubString(SString &Sub,SString S,int pos,int len){
//子串范围越界
if (pos+len-1 > S.length)
return false;
for (int i=pos; i<pos+len; i++)
Sub.ch[i-pos+1] = S.ch[i];
Sub.length = len;
return true;
}
StrCompare(S,T):比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。
//比较操作。若S>T,则返回值>0; 若S=T,则返回值=0; 若S<T,则返回值<0
int StrCompare(SString S,SString T) {
for (int i=1; i<=S.length && i<=T.length; i++){
if (S.ch[il!=T.ch[i])
return S.ch[i]-T.ch[i];
}
//扫描过的所有字符都相同,则长度长的串更大
return S.length-T.length;
}
Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0。(朴素模式匹配算法)
int Index(SString S,SString T){
int i=1,n=StrLength(S),m=StrLength(T);
SString sub;//用于暂存子串
while(i<=n-m+1){ //最多对比n-m+1个子串
SubString(sub,S,i,m); //取出从位置i开始,长度为m的子串
if(StrCompare(sub,T)!=0) //子串和模式串对比,若不匹配,则匹配下一个子串
++i;
else
return i; //返回子串在主串中的位置
}
return 0; //S中不存在与T相等的子串
}
4.2 串的模式匹配
字符串模式匹配:在主串中找到与模式串相同的子串,并返回其在位置。
子串----主串的一部分,一定存在
模式串----不一定能在主串中找到
朴素模式匹配算法
主串长度为n,模式串长度m
朴素模式匹配算法:将主串中所有长度为m的子串(最多对比n-m+1个子串)依次与模式串对比,直到找到一个完全匹配子串,或所有的子串不匹配为止。
操作步骤:
- 若当前⼦串匹配失败,则主串指针 i 指向下⼀个⼦串的第⼀个位置,模式串指针 j 回到模式串的第⼀个位置
- 若 j > T.length,则当前⼦串匹配成功,返回当前⼦串第⼀个字符的位置 —— i - T.length
int Index(SString S,SString T){
int i=1,j=1;
while(i<=S.length && j<=T.length{
if(S.ch[i]==T.ch[i]){
++i;
++j; //继续比较后继字符
}
else{
i=i-j+2;
j=1; //指针后退重新开始匹配
}
}
if(j>T.length)
return i-T.length;
else
return 0;
}
kmp算法&&kmp优化
int Index_KMP(SString S,SString T,int next[]){
int i=1,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数组
next数组的优化思路—nextval数组
手算解题:先求next数组,再由next数组求nextval数组
nextval[1]=0;
for (int j=2; j<=T.length; j++){
if(T.ch[next[j]]==T.ch[j])
nextval[jl=nextval[next[j]];
else
nextval[j]=next[j];
}
nextval只要会手算就行