1.堆分配存储表示(也是一种顺序表)
typedef struct{
char *ch;
int length;
}HString;
2.串操作函数
//初始化一个串
void InitalStr(HString &T);
//生成一个其值等于串常量chars的串T.
void StrAssign(HString &T, char *chars);
//返回串的长度
int StrLength(HString &T);
//比较串大小,从第一个开始比较,若T>S返回>0,若S=T 返回0;若T<S返回<0
int StrCompare(HString &T, HString &S);
//将T清空为空串
int ClearString(HString &T);
//用T返回S1和S2连接的新串
void Concat(HString &T, HString &S1, HString &S2);
//用Sub返回串T的第Pos个字符,长度为len的子串
int SubString(HString &Sub, HString &T, int pos, int len);
3.函数实现
#include<stdio.h>
#include<stdlib.h>
#include"HStringOp.h"
//初始化一个串
void InitalStr(HString &T){
T.ch = NULL;
T.length = 0;
}
//生成一个其值等于串常量chars的串T.
void StrAssign(HString &T,char *chars){
int i = 0,j=0;
char *c;
if (T.ch)free(T.ch);
for (i = 0, c = chars; *c; ++i, ++c);
if (!i)
{
T.ch = NULL;
T.length = 0;
}
else
{
if (!(T.ch = (char *)malloc(i*sizeof(char))))exit;
while (j<i)
{
T.ch[j] = chars[j];
j++;
}
T.length = i;
}
}
//返回串的长度
int StrLength(HString &T){
return T.length;
}
//比较串大小,从第一个开始比较,若T>S返回>0,若S=T 返回0;若T<S返回<0
int StrCompare(HString &T, HString &S){
int i = 0;
for ( i = 0; i < T.length&&i<S.length; i++)
{
if (T.ch[i]!=S.ch[i])
{
return T.ch[i] - S.ch[i];
}
}
return T.length - S.length;
}
//将T清空为空串
int ClearString(HString &T){
if (T.length == 0)return 1;
free(T.ch);
T.ch = NULL;
T.length = 0;
return 1;
}
//用T返回S1和S2连接的新串
void Concat(HString &T,HString &S1,HString &S2){
if (T.ch)free(T.ch);
if (!(T.ch=(char *)malloc((S1.length+S2.length)*sizeof(char))))exit;
for (int i = 0; i < S1.length; i++)
{
T.ch[i] = S1.ch[i];
}
for (int i = S1.length; i < S1.length+S2.length; i++)
{
T.ch[i] = S2.ch[i-S1.length];
}
T.length = S1.length + S2.length;
}
//用Sub返回串T的第Pos个字符,长度为len的子串
int SubString(HString &Sub,HString &T,int pos,int len){
if (!T.length)return 0;
if (pos > T.length)return 0;
if (Sub.ch)free(Sub.ch);
if (T.length<(pos+len-1))Sub.length = T.length - pos + 1;
else Sub.length = len;
Sub.ch = (char *)malloc(Sub.length*sizeof(char));
for (int i = 0; i < Sub.length; i++)
{
Sub.ch[i] = T.ch[i + pos-1];
}
return 1;
}
4.子串位置定位一般算法,返回第pos个字符后子串的位置
int pos_substr(HString &F,HString &S,int pos){
int i = pos, j = 0;
int Flength = StrLength(F);
int Slength = StrLength(S);
if (Slength+pos>Flength)
{
return 0;
}
while (i<Flength&&j<Slength)
{
if (F.ch[i]==S.ch[j])
{
++i; ++j;
}else
{
i=i-j+1; j = 0;
}
}
if (j >=Slength)return i+1 - Slength;
else return 0;
}
5.KMP算法
(1)求next函数
//next函数求值
void get_next(HString &S,int *p){
int i = 0, j = 0;
i = 0; *p = 0;
while (i<S.length-1) //书中T[0]存放的是字符串的长度,我们这里T[0]也属于字符串的内容
{
/*
实际上求next算法也是一个匹配的过程
当ch[i]==ch[j-1]时说明,主串第i+1个(我们这里字符串从0开始)之前有j个字符与子串匹配。则p[i+1]=j;同时继续比较ch[i+1]=ch[j]
当ch[i]!=ch[j-1]时说明,主串第i个字符与子串第j-1个字符适配,这时候需要获取子串的第j-1个next个值,再与主串进行比较
这里表示next值的指针也是从0标号开始,与书上不同。
*/
if (j==0||S.ch[i]==S.ch[j-1]){
i++; j++;
p[i] = j;
}
else
{
j = p[j-1];
}
}
}
求next函数改进算法
//KMP模式匹配改进算法
void get_nextval(HString &S, int *p){
int i = 0, j = 0;
i = 0; *p = 0;
while (i < S.length - 1) //书中T[0]存放的是字符串的长度,我们这里T[0]也属于字符串的内容
{
if (j == 0 || S.ch[i] == S.ch[j - 1]){
i++; j++;
if (S.ch[i]!=S.ch[j-1])
{
p[i] = j;
}
else{
p[i] = p[j-1];
}
}
else
{
j = p[j - 1];
}
}
}
(2)KMP实现定子串位置函数
//KMP模式匹配算法
int Index_KMP(HString T,HString S,int pos,int *p){
int i = pos, j = 0;
while (i<S.length&&j<T.length)
{
if (S.ch[i]==T.ch[j])
{
i++; j++;
}
else
{
j = p[j];
if (j==0)
{
i++;
}
else
{
j--;
}
}
}
if (j>=T.length)
{
return i - T.length+1;
}
else
{
return 0;
}
}