串的存储结构
1、顺序存储
静态数组
//静态数组实现串的顺序存储
typedef struct {
char ch[maxsize];
int length;//串的实际长度,maxsize是分配的最大可存储长度
}SString;
动态数组
//动态数组实现串的顺序存储
typedef struct{
char *ch;
int length;
}HString;//动态数组实现 堆分配存储
HString S;
//动态数组顺序存储的串初始化
void InitString(HString &S){
S.ch=(char *)malloc (sizeof(char)*maxsize);
S.length=0;
}
2、链式存储
//链式存储
typedef struct StringNode{
char ch[4];//每个结点存储多个字符,提高存储密度
struct StringNode * next;
}StringNode,*String;
求子串(顺序静态数组存储结构)
//将主串S中第pos个位置开始的长度为len的子串返回给子串sub
bool SubString(SString S,SString &sub,int pos,int len){
//子串范围越界
if(pos+len-1>S.length)
return false;
for(int i=pos;i<pos+len;i++){
sub.ch[i]=S.ch[i];
}
sub.length=len;
return true;
}
两个字符串的比较
int StrCompare(SString S,SString T){
for(int i=0;i<S.length&&i<T.length;i++){
if(S.ch[i]!=T.ch[i])
return S.ch[i]-T.ch[i];
}
//扫描过的所有字符串都相同且字符串长度一样,返回0,匹配成功
//前面扫描过的所有自负还都相同,但是字符串长度不一样,任然要返回比较结果
return S.length-T.length;
}
字符串定位
//字符串定位,若主串中存在与串T值相同的子串,则返回它在主串中第一次出现的位置,否则函数值返回-1。
int index(SString S,SString T){
int i=0;
SString sub;
//从主串中依次循环取出串T长度的子串sub,和串T进行比较,直到找到或扫描结束
while(i<S.length-T.length+1){
SubString(sub,S,i,T.length);//在主串下标i处开始取得子串sub,长度为T.length
//比较
if(StrCompare(sub,T)!=0)
//该子串比较不匹配,下一个
++i;
else
//找到匹配的子串了
return i;
}
return -1;
}
字符串朴素模式匹配
int Index(SString S,SString T){
int i=1,j=1;//从主串S和模式串T下标为1处开始扫描匹配,舍弃ch[0]不存数据
while(i<=S.length-T.length+1&&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;//i当前在匹配成功的字符子串的最后一个位置,i-T.length回到匹配成功的第一个位置
//匹配失败,返回0
else
return 0;
}
字符串匹配——KMP算法
int Index_KMP(SString S,SString T,int next[]){
int i=1,j=1;
while(i<=S.length-T.length+1&&j<T.length){
//j=0说明模式串与主串第一个字符匹配失败,继续(从子串第一个字符开始)匹配下一个子串
if(j==0||S.ch[i]==T.ch[i]){
i++;j++;
}
else{
j=next[j];
//主串指针i不回溯,保持不变,模式串的指针指向next[j]对应的位置,
//如果next[j]对应的位置为0,说明是模式串与主串第一个字符匹配失败,继续(从子串第一个字符开始)匹配下一个子串
}
}
if(j>T.length)
//i当前在匹配成功的字符子串的最后一个位置,i-T.length回到匹配成功的第一个位置
return i-T.length;
else
return 0;
}