头文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
定义串的结构体
typedef struct
{
char * ch;
int length;
}HString;
(1)串的初始化
void Init_String(HString * s) //初始化
{
s->ch=NULL;
s->length=0;
}
(2)赋值,把串str复制到串s
short StrAssign(HString * s, char * str) //赋值
{
int i;
int len=strlen(str);
free(s->ch);
s->ch=(char*)malloc(sizeof(char)*len);
if(s->ch==NULL)
return 0;
for(i=0; i<len; i++)
{
s->ch[i]=str[i];
}
s->length=len;
return 1;
}
(3)打印串
void Print(HString * s) //打印
{
int i;
for(i=0; i<s->length; i++)
{
printf("%c", s->ch[i]);
}
printf("\n");
}
(4)复制操作,由串s复制得到串p
void StrCopy(HString * p, HString * s) //由串s复制得到串p
{
int i;
p->ch=(char*)malloc(sizeof(char));
for(i=0; i<s->length; i++)
{
p->ch[i]=s->ch[i];
}
p->length=s->length;
}
(5) 判断串是否为空
short StrEmpty(HString * s) //判断是否为空
{
if(s->length==0)
return 1;
else
return 0;
}
(6) 比较两串长度,s大于p返回1,小于返回-1,等于返回0
short StrCompare(HString * s, HString * p) //比较两串长度
{
int i=0;
int j=0;
if(s->length==0 && p->length==0)
return 0;
while(i<s->length && j<p->length)
{
if(s->ch[i] > p->ch[i])
return 1;
else if(s->ch[i] < p->ch[i])
return -1;
else
{
i++;
j++;
}
}
if(i<s->length)
return 1;
else
return -1;
}
(7) 返回串长度
int StrLength(HString * s) //返回串长度
{
return s->length;
}
(8)求子串
void SubString(HString * sub, HString * s, int pos, int len) //求子串
{
int i;
int j=pos;
if(pos<0 || pos>s->length || len<0 || len>s->length-pos+1)
return;
if(sub->ch!=NULL)
free(sub->ch);
sub->ch=(char*)malloc(sizeof(char)*len);
for(i=0; i<len; i++)
{
sub->ch[i]=s->ch[j+i];
}
//sub->ch[i+1]='\0';
sub->length=len;
}
(9)串连接
void Concat(HString * T, HString * s1, HString * s2) //s1和s2连接
{
int len;
int i,j;
if(T->ch!=NULL)
free(T->ch);
len=s1->length+s2->length;
T->ch=(char*)malloc(sizeof(char)*len);
for(i=0; i<s1->length; i++)
{
T->ch[i]=s1->ch[i];
}
for(j=0; j<s2->length; j++)
{
T->ch[j+i]=s2->ch[j];
}
T->length=len;
}
(10)定位操作,若主串s中存在与串p相同值的子串,则返回它在主串s中第一次出现的位置;否则函数值为0
int Index(HString s, HString p) //定位操作(朴素模式匹配算法)
{
int i=1, j=1;
while(i<=s.length && j<=p.length)
{
if(s.ch[i]==p.ch[j])
{
i++;
j++;
}
else
{
i=i-j+2;
j=1;
}
}
if(j>p.length)
return i-p.length;
else
return 0;
}
(11)清空串 ,将s清位空串
void ClearString(HString * s) //清空串
{
s->length=0;
if(s->ch!=NULL)
free(s->ch);
s->ch=NULL;
}
(12)销毁串
void DestroyString(HString * s) //销毁串
{
free(s->ch);
}
(13)KMP匹配算法求next数组
void get_next(HString p, int next[]) //KMP匹配算法求next数组(数据多了数组就有点问题,还没有排查出)
{
int j=0; //前缀
int i=1; //后缀
next[1]=0;
while(i<p.length)
{
if(j==0 || p.ch[i]==p.ch[j])
{
++i;
++j;
next[i]=j;
}
else
j=next[j];
}
}
(14) KMP匹配算法定位
int Index_KMP(HString s, HString p) //KMP匹配算法
{
/*不能使用:int next[p.length+1]
原因:如果一个数组大小是变量定义,则在程序运行前不能确定数组大小,也就无法申请,故不允许*/
int * next=(int*)malloc(sizeof(int)*(p.length+1));
int i=1, j=1;
get_next(p,next);
while(i<=s.length && j<=p.length)
{
if(j==0 || s.ch[i]==p.ch[j])
{
++i;
++j;
}
else
j=next[j];
}
if(j>p.length)
return i-p.length;
else
return 0;
}
(15) 打印next数组
void Print_next( HString p, int next[]) //打印next数组
{
int n;
for(n=1; n<=p.length; n++)
{
printf("%d", next[n]);
}
printf("\n");
}
主函数:
main()
{
HString s, p, sub, T;
HString s1, s2;
int n; int next[30];
int pos=0; int len=4;
char str[20]="abcaaba";
char st[10]="aaba";
s.ch=(char*)malloc(sizeof(char));
p.ch=(char*)malloc(sizeof(char));
Init_String(&s);
Init_String(&p);
Init_String(&sub);
Init_String(&T);
Init_String(&s1);
Init_String(&s2);
StrAssign(&s, str);
StrAssign(&p, st);
printf("(1)打印串s :");
Print(&s);
printf("(2)打印串p :");
/*StrCopy(&p, &s);*/
Print(&p);
printf("(3)判断串是否为空:");
if(StrEmpty(&s))
printf("串s为空\n");
else
printf("串s不为空\n");
printf("(4)比较串s和串p的长度:");
if(StrCompare(&s, &p)==1)
printf("串s>串p\n");
else if(StrCompare(&s, &p)==0)
printf("串s=串p\n");
else
printf("串s<串p\n");
printf("(5)s串长:%d\n", StrLength(&s));
printf("(6)求子串:");
SubString(&sub, &s,pos,len); //sub记得初始化
Print(&sub);
printf("(7)连接s和p,用T返回:");
Concat(&T, &s, &p);
Print(&T);
printf("(8)朴素算法定位:%d\n",Index(s, p)); //串的第一位废弃不用
//printf("(9)清空串\n");
//ClearString(&s);
//
//printf("(10)销毁串\n");
//DestroyString(&s);
printf("(11)KMP算法得到next数组:");
get_next(p, next);
Print_next(p, next);
printf("(12)KMP算法定位:%d\n",Index_KMP(s, p)); //运行此行代码时记得注释(9)(10),否侧匹配失败
}