串-字符串
本章重点考察KMP算法求next函数
串的定义
由零个或多个字符组成的有限序列
记作:s=’a1a2...an'
串的表示和实现
1.定长顺序存储的表示
//串定长顺序存储表示
#define MAXSRELEN 255//用户可在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN+1]; //0号单元存放串的长度
基本操作为“字符序列的复制”
2.堆分配存储表示(常用)
由C语言动态分配函数malloc和free来管理。
//串的堆分配存储表示
typedef struct
{
char *ch;//若是非空串,则按串长分配存储区,否则ch为NULL
int length; //串长度
} HString;
实现算法为:先为新生成的串分配一个存储空间,然后进行串值的复制
//由T返回S1和S2连接而成的新串
Status Concat(HString &T,HString S1,HString S2)
{
if(T.ch) free(ch);
if(!(T.ch=(char*)malloc(S1.length+S2.length)))*sizeof(char);
T.ch[0..S1.length-1]=S1.ch[0..S1.length-1];
T.length=S1.length+S2.length;
T.ch[S1.length..T.length-1]=S2.ch[0..S2.length-1];
return OK;
}
3.串的块链存储表示
存储密度=数据元素所占的存储位/实际分配的存储位
串的模式匹配算法
子串的定位操作通常称为串的模式匹配(其中T称为模式串)
采用定长顺序存储结构
1.普通算法
每次从主串S的第pos个字符与模式的第一个字符比较。若相等,则继续逐个比较后续字符;否则从主串的下一个字符再重新和模式字符比较。
int Index(SString,SString T,int pos)
//返回字串在主串S在第pos个元素之后的位置 ,不存在则返回0
//其中T非空,1<=pos<=StrLength(s)
{
i=pos;
j=1;
while(i<=S[0]&&j<=T[0])//0号单元存放串的长度
{
if(S[i]==T[j])
{
++i;
++j;//继续比较后即字符
}
else
{
i=i-j+2;
j=1; //指针后退重新开始匹配
}
}
if(j>T(0)) return i-T[0];
else return 0;
}
2.KMP算法
改进在于:每一趟匹配字符比较不等时,不需回溯i指针。而是利用已经得到的“部分匹配”结果向右滑动尽可能远的一段距离后,继续进行比较。
int Index_KMP(SString S,SString T,int pos)
//利用模式串T的next()函数求T在主串S中第pos个字符之后的位置的KMP算法
//其中,T非空,1<=pos<=SreLength(S)
{
i=pos; j=1;
while(i<=S[0]&&j<=T[0])
{
if(j==0||S[i]==T[j])
{
++i;
++j;
}
else
{
j=next[j];//模式串向右移动
}
}
if(j>T(0))
return i-T[0];
else return 0;
}
next函数值求法
next[j]=0 当j=1时
next[j]=Max{k|1<k<j且 ‘p1...pk-1' = 'pj-k+1...pj-1'} 当集合非空时
next[j]=1 其他情况
算法
void get_next(SString T,int next[])
//求模式串T中的next值并存入数组next
{
i=1; next[1]=0; j=0;
while(i<T[0])
{
if(j==0||T[i]==T[j])
{
++i;
++j;
next[i]=j;
}
else j=next[j];
}
}
模式串中连续元素相同,对next函数值进行修正
void get_nextval(SString T,int next[])
//求模式串T中的nextval值并存入数组nextval
{
i=1; nextval[1]=0; j=0;
while(i<T[0])
{
if(j==0||T[i]==T[j])
{
++i;
++j;
if(T[i]!=T[j]) nextval[i]=j;
else nextval[i]=nextval[j];
}
else j=nextval[j];
}
}