1.串的实现相比较而言简单一些,但个人觉得有一些需要注意的地方,以下一 一列举:
(1)串基本术语:
空串:空串指长度为0的串,其不包含任何字符;
空格串:不同于空串,它是由一个或多个空格构成的串。虽然是空格,但在计算长度时要把空格的个数算在内;
串比较:串的大小比较时以字符的ASCII码值作为依据。
(2)串基本操作:赋值操作、连接操作、求串长、窜的比较和求子串。
(3)串的存储结构:顺序存储和链式存储。其中链式存储可以指定节点大小,存储若干个字符。
2.串的模式匹配算法:求解子串在主串中首次出现的位置:Index(S,T,pos)
算法的实现使具有暴力的性质,模式串和主串同时从第一个位置开始进行判断,若对应位置字符相等则继续向后判断,若不相
等,则模式串回到串首,主串字符位置指针回退,重新匹配。
int Index(String s,String t,int pos){
//返回子串t在主串s中第pos个字符之后的位置,若不存在,则返回0
if(isEmpty(t) || pos<0 || pos>t.length-1) exit(0);
int i=pos;
int j=0;
while(i<=s.length && j<=t.length){
if(s.ch[i] == t.ch[j]){
++i;
++j; //继续比较后续的字符
}
else{
i=i-j+1;j=0;//指针回退,重新开始匹配
}
}
if(j>t.length) {
return i-t.length;
}
else
return 0;
}
串的模式匹配算法优化:KMP算法
此算法可以在O(m+n)的数量级上完成串的匹配操作。其改进在于,每一趟匹配过程中出现字符比较不相等的时候,不需要回
退指针i,而是利用已经匹配到的部分结果将模式串向右滑动尽可能远的距离,继续匹配。
#include
#include
using namespace std;
#define MAXSTRLEN 100
typedef char SString[MAXSTRLEN+1];
//返回模式串T在主串中第pos位置之后的位置,若存在,返回1,否则返回0
int KMPindex(SString S,SString T,int pos){
if(pos < 1 || pos>S[0]) exit(0);
int i=pos;
int j=1;
int next[MAXSTRLEN];
GetNext(T,next);
while(i <= S[0] && j<= T[0]){
if(S[i] == T[j]){
i++;j++;
}else{
j=next[j];
}
}
if(j >T[0]) return i-T[0];
return 0;
}
//求子串next[i]的值
void GetNext(SString T,int next[]){
int j=1,k=0;
next[1]=0;
while(j
++j;
++k;
next[j]=k;
}else{
k = next[k];
}
}
}
int main()
{
SString S = {13,'a','b','a','b','c','a','b','c','a','c','b','a','b'};
SString T = {5,'a','b','c','a','c'};
int pos;
pos = KMPindex( S, T, 1);
cout<<"匹配位置为:"<
}
3.顺序串与链式串的实现(C语言)
(1)顺序串:
#include
#include
#include
using namespace std;
#define MAXSIZE 100
//串的顺序存储
typedef struct st{
char *ch;//串存放的起始地址
int length;//串的长度
int strsize;//分配的存储空间的大小
}String;
//1.串的初始化操作
String CreateNullString(){
String str;
str.length = 0;
str.ch = (char *)malloc(MAXSIZE*sizeof(char));
str.strsize = MAXSIZE;
return str;
}
//2.判断空串
int isEmpty(String str){
if(str.length == 0){
return 1;
}else{
return 0;
}
}
//3.串的赋值操作
void StrAssign(String *str1,char str2[]){
int i=0;
while(str2[i] != '\0') i++;//计算str2的长度
if(str1->length < i){ //结构指针成员的访问
//增加存储空间,将较长的空间赋值为新的值
str1->ch = (char *)malloc(sizeof(char));
str1->strsize = i;
}
str1->length = i;
for(i=0;i
str1->ch[i] = str2[i];//从第一个字符开始,着个赋值
}
}
//4.串的拷贝
void StrCopy(String *str1,String str2){
if(str1->strsize < str2.strsize){
str1->ch = (char *)realloc(str1->ch,str2.length*sizeof(char));
str1->strsize = str2.length;;
}
str1->length = str2.length;
int i;
for(i=0;i
str1->ch[i] = str2.ch[i];
}
}
//5.串的长度
int StrLength(String str){
return str.length;
}
//6.串的连接操作
void StrConcat(String *str,String str1,String str2){
if(str->strsize < str1.strsize + str2.strsize){
str->ch = (char *)realloc(str->ch,(str1.length+str2.length)*sizeof(char));
str->strsize = str1.length+str2.length;
}
str->length = str1.length+str2.length;
int i;
for(i=0;i
}//将str1赋值到str
for(;i
str->ch[i] = str2.ch[i-str1.length];
}//将str2赋值到str
}
//7.取子串
int SubStr(String s,int i,int len,String *t){
/*
i表示从字符串s的第i个位置开始截取(索引从1开始)
len表示截取字符串的长度
*/
//将s中从i位置起,len长度的串通过t返回
if(i<=0 || i>s.length || len<0 || len>s.length-i+1){
t->ch = (char *)realloc(t->ch,len*sizeof(char));
t->strsize = len;
}
t->length = len;
int k;
for(k=0;k
t->ch[k] = s.ch[i-1+k];
}
return 1;
}
//8.插入操作
int InsertString(String *str,int i,String str1){
//将str1,插入str的第i个位置
if(i <= 0 || i>str->length+1) return 0;
if(str->strsize < str->length + str1.length){
//空间不足
str->ch = (char *)realloc(str->ch,(str->length+str1.length)*sizeof(char));
str->strsize = str->length + str1.length;
}
int k;
for(k=str->length-1;k>=i-1;k--){
//将str中的后i个字符后移
str->ch[k+str1.length] = str->ch[k];
}
str->length = str->length + str1.length;
for(k=0;k
}
return 1;
}
//9.删除子串
int deleteStr(String *str,int i,int len){
//从第i个位置开始,删除len长度的子串
if(i<=0 || i>str->length || len <0 || len > str->length-i+1){
return 0;
}
int k;
for(k=i+len-1;k
//从str的i+len-1个位置开始将其后的所有字前移
str->ch[k-len] = str->ch[k];
}
str->length -= len;
return 1;
}
//10.输出操作
void print(String *str){
int i;
for(i=0;i
cout<
}
cout<
//11.串的模式匹配
int Index(String s,String t,int pos){
//返回子串t在主串s中第pos个字符之后的位置,若不存在,则返回0
if(isEmpty(t) || pos<0 || pos>t.length-1) exit(0);
int i=pos;
int j=0;
while(i<=s.length && j<=t.length){
if(s.ch[i] == t.ch[j]){
++i;
++j; //继续比较后续的字符
}
else{
i=i-j+1;j=0;//指针回退,重新开始匹配
}
}
if(j>t.length) {
return i-t.length;
}
else
return 0;
}
int main()
{
String str1 = CreateNullString();
String str2 = CreateNullString();
String str3 = CreateNullString();
char ch[MAXSIZE];
cout<<"请输入主串"<
StrAssign(&str1,ch);
cout<<"主串为:";
print(&str1);
cout<
cout<<"拷贝得到的串为:";
print(&str2);
cout<
SubStr(str1,4,4,&str3);
cout<<"截取的子串为:";
print(&str3);
cout<
int pos = Index(str1,str2,0);
cout<<"匹配位置为:"<
}
(2)链式串:
#include
#include
using namespace std;
//串的链式存储
typedef struct node{
char ch; //字符域
struct node *next; //指针域,存放下一个节点的指针
}node,*Linkstr;
//1.初始化一个空串
Linkstr CreateNullString()
{
Linkstr str;
str=(Linkstr)malloc(sizeof(node));
if(str != NULL){
str->next = NULL;
}
return str;
}
//2.判断空串
int IsEmpty(Linkstr str)
{
if(str->next ==NULL){
return 1;
}
else{
return 0;
}
}
//3.赋值操作
void StringAssign(Linkstr str,char t[])
{
Linkstr p,q,r;
r=str;//r始终表示的尾节点(最后一个非空节点,而不是最后一个NULL节点)。
q=str->next;
int i;
for(i=0;t[i] != '\0';i++){
if(q!=NULL)
{
q->ch = t[i]; //一个一个的存入节点
r=q;
q=q->next;
}
else{
//(初始化时只给头结点分配了存储空间或者其他情况),如果需要继续添加数据(其他节点没分配空间)需要继续分配
p=(Linkstr)malloc(sizeof(node));
//添加节点
p->ch = t[i];
r->next = p;
r = p;
}
r->next = NULL;
//将s中多余的空间释放掉
while(q!=NULL){
p=p->next;
free(q);
q=p;
}
}
}
//2.串的拷贝
void Assign(Linkstr s,Linkstr t)
{
////将t串的值赋值给s串
Linkstr p,q,r,u;
p=t->next;
q=s->next;
r=s;
while(p!=NULL){
//串s已经分配了空间
if(q!=NULL){
q->ch = p->ch;
r=q;
q=q->next;
}
else{
//串s中原先的空间不够
u=(Linkstr)malloc(sizeof(node));
u->ch = p->ch;
r->next =u;
r=u;
}
//p节点后移
p=p->next;
//同理,若q的长度过长,可以释放多余的空间
while(q!= NULL){
p=p->next;
free(q);
q=p;
}
r->next = NULL;
}
}
//3.求串长
int length(Linkstr s)
{
Linkstr p;
int len=0;
p=s->next;
while(p!=NULL){
len++;
p=p->next;
}
return len;
}
//4.串的链接操作
void contact(Linkstr s,Linkstr s1,Linkstr s2)
{
Linkstr p,q,r,t;
r=s;
p=s1->next;
q=s->next;
while(p!=NULL){
if(q!=NULL) //s不是空串
{
q->ch = p->ch;
q=q->next;
r=q;
}
else{
//串s原来没有分配存储空间,需要申请空间
t=(Linkstr)malloc(sizeof(node));
t->ch=p->ch;
r->next=t;
r=t;
}
p=p->next;
}
p=s2->next;
while(p!=NULL){
if(q!=NULL){
q->ch=p->ch;
q=q->next;
r=q;
}else{
//串s原来没有分配存储空间,需要申请空间
t=(Linkstr)malloc(sizeof(node));
t->ch=p->ch;
r->next=t;
r=t;
}
p=p->next;
}
//将串s的多余的空间清除掉(这个情况只可能发生在while的if循环中)
while(q!=NULL){
p=q->next;
free(q);
q=p;
}
r->next = NULL;
}
//5.截取子串
int subString(Linkstr s,int i,int len,Linkstr t)
{
Linkstr p,q,r,u;
if(i<=0||i>length(s) || i+len-1>length(s))
return 0;
//指针指向s的第i-1个位置
int j,k;
for(j=0,p=s;j p=p->next;
}
for(k=0,r=t,q=t->next;k
if(q!=NULL){
q->ch=p->ch;
r=q;
q=q->next;
}
else{
u=(Linkstr)malloc(sizeof(node));
u->ch=p->ch;
r->next=u;
r=u;
}
p=p->next;
}
while(q!=NULL){
p=q->next;
free(q);
q=p;
}
r->next=NULL;
return 1;
}
//6.插入子串操作
int insert(Linkstr s,int i,Linkstr t)
{
Linkstr p,q,r;
if(i<=0 || i>length(s)+1)
return 0;
//指向i-1个位置
int j;
for(j=0,p=s;j
}
q=t->next;
while(q!=NULL)
{
r=(Linkstr)malloc(sizeof(node));
r->ch = q->ch;
r->next=p->next;
p->next=r;
q=q->next;
p=r;
}
return 1;
}
//7.删除操作
int deleteStr(Linkstr s,int i,int len){
Linkstr p,q,r;
if(i<=0 || i>length(s) || i+len-1>length(s))
return 0;
int j;
for(j=0,p=s;j
}
for(j=0;j
p->next=q->next;
free(q);
}
return 1;
}
//8.打印输出
void print(Linkstr s)
{
Linkstr p=s->next;
while(p!=NULL)
{
cout<
p=p->next;
}
cout<
int main()
{
Linkstr s1;
Linkstr s2;
Linkstr s3;
s1=CreateNullString();
s2=CreateNullString();
s3=CreateNullString();
char str[100];
cout<<"请输入字符:"<
StringAssign(s1,str);
cout<<"串1:";
print(s1);
cout<
Assign(s2,s1);
cout<<"串2:";
print(s2);
cout<
cout<<"串s2的删除操作:"<
cout<<"串2:";
print(s2);
cout<
cout<<"串3为(串1和串2的连接):";
print(s3);
return 0;
}