1.串的定义和基本操作
字符串(String)是由零个或多个字符组成的有限序列。
S=“a1a2a3.....an”(n≥0)
字串:串中任意个连续的字符组成的子序列。
主串:包含字串的串。
字符在主串中的位置:字符在串中的序号。
字串在主串中的位置:字串的第一个字符在主串中的位置。
空串:M=“” 空格串:“ ”
串是一种特殊的线性表,数据元素之间呈线性关系。
串的基本操作:如增删改查等通常以字串为操作对象。
假设有串T="",S="iPhone 11 Pro Max?”,W="Pro”
StrAssign(&T,chars):赋值操作。把串T赋值为chars。
StrCopy(&T,S);复制操作。由串S复制得到串T。
StrEmpty(S):判空操作。若S为空串,则返回TRUE,否则返回FALSE。
StrLength(S):求串长。返回串S的元素个数。
ClearString(&S):清空操作。将S清为空串。
DestroyString(&S):销毁串。将串S销毁(回收存储空间)。
Concat(&T,S1,S2):串联接。用T返回由S1和S2联接而成的新串
SubString(&Sub,S,pos,len):求子串。用Sub返回串S的第pos个字符起长度为len的子串。
Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的
位置;否则函数值为0。
StrCompare(S,T):比较操作。若S>T, 则返回值>0;若S=T, 则返回值=0;若S<T, 则返回值<0。
Eg:执行基本操作Concat(&T, S, W)后,T="iPhone 11 Pro Max?Pro"
执行基本操作SubString(&T ,S, 4, 6)后,T="one 11”
执行基本操作Index(S, W)后,返回值为11
2.串的存储结构
串的顺序存储:
//串的顺序存储
#define MAXLEN 255
typedef struct{
char ch[MAXLEN]; //每个分量存储一个字符
int length;
}SString;
typedef struct{
char *ch; //按串长分配存储区,ch指向串的基地址
int length;
}SString;
SString S;
S.ch=(char*)malloc(MAXLEN * sizeof(char));
S.length=0;
串的链式存储:
//串的链式存储
#define MAXLEN 255
typedef struct StringNode{
char ch; //每个结点存储一个字符
struct StringNode *next;
}StringNode,*String;
//存储密度低,每个字符1B,每个指针4B
typedef struct StringNode{
char ch[4]; //每个结点存储多个字符
struct StringNode *next;
}StringNode,*String;
//存储密度高
串的顺序存储案例:
//串的顺序存储
#include<stdio.h>
#include<stdlib.h>
#define MAXLEN 100
typedef struct{
char ch[MAXLEN]; //每个分量存储一个字符,0号不存储
int length; //串的长度
}SString;
//初始化
bool StringAssign(SString &S,char ch[]){
int i=0;
while(ch[i]!='\0'){
S.ch[i+1]=ch[i];
++i;
}
S.length=i;
return 0;
}
//求串的长度
int StrLength(SString S){
return S.length;
}
//求字串 (sub返回串S的第pos个字符起长度为len)
bool SubString(SString &Sub,SString S,int pos,int len){
if(pos+len-1>S.length)
return false;
for(int i=pos;i<pos+len;i++){
Sub.ch[i-pos+1] = S.ch[i]; //0下标不存数据
}
Sub.length=len;
return true;
}
//比较操作
int StrCompare(SString S,SString T){
for(int i=1;i<=S.length && i<=T.length;i++){
if(S.ch[i]!=T.ch[i]){
return S.ch[i]-T.ch[i];
}
}
return S.length-T.length;
}
//定位操作
//若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置
int Index(SString S,SString T){
int i=1;
int n=StrLength(S);
int m=StrLength(T);
SString sub; //暂存字串
while(i<=n-m+1){
SubString(sub,S,i,m);
if(StrCompare(sub,T)!=0){
++i;
}else{
return i;
}
}
return 0;
}
//打印
int ShowString(SString &S){
if(S.length==0){
printf("当前串为空");
return 0;
}
for(int i=1;i<=S.length;i++){
printf("%c",S.ch[i]);
}
printf("\n");
return 0;
}
int main(){
SString S; //主串
char ch[]={"hello world!"};
StringAssign(S,ch);
printf("主串S-ch:");
ShowString(S);
SString T; //子串
char cl[]={"world"};
StringAssign(T,cl);
printf("字串S-cl:");
ShowString(T);
//求字串 (sub返回串S的第pos个字符起长度为len)
SString Sub;
SubString(Sub,S,3,7);
printf("S的字串:");
ShowString(Sub);
//比较操作
int com= StrCompare(S,T);
printf("Compare :%d\n",com);
//若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置
int de= Index(S,T);
printf("字串在主串中的位置:%d",de);
}
结果:
主串S-ch:hello world!
字串S-cl:world
S的字串:llo wor
Compare :-15
字串在主串中的位置:7
3.字符串的模式匹配
4.KMP算法
![](https://img-blog.csdnimg.cn/direct/d709f9de634b4708a27ef45d847276bb.png)
![](https://img-blog.csdnimg.cn/direct/1e77221b2bff4a7bafe4bbfd485cb739.png)
![](https://img-blog.csdnimg.cn/direct/aaa44c0cfcef4f8e9997def67cbbd4ae.png)
![](https://img-blog.csdnimg.cn/direct/3d87fb51b7a946ac97812423b205be9e.png)
5.求next数组
6.KMP算法的优化
KMP综合案例:
#include<stdio.h>
#include<stdlib.h>
#define MAXLEN 100
typedef struct{
char ch[MAXLEN]; //每个分量存储一个字符,0号不存储
int length; //串的长度
}SString;
bool StringAssign(SString &S,char ch[]){
int i=0;
while(ch[i]!='\0'){
S.ch[i+1]=ch[i];
i++;
}
S.length=i;
printf("len=%d\n",i);
return 0;
}
int ShowString(SString &S){
if(S.length==0){
printf("当前串为空");
return 0;
}
for(int i=1;i<=S.length;i++){
printf("%c",S.ch[i]);
}
printf("\n");
return 0;
}
//模式串T的next数组
void get_next(SString T,int next[]){
int i=1,j=0;
next[1]=0;
while(i<T.length){
if(j==0 || T.ch[i] == T.ch[j]){
++i;
++j;
next[i]=j;//若pi=pj,则next[j+1]=next[j]+1
}else{
j=next[j];//否则j=next[j],循环继续
}
}
}
//KMP算法
int Index_KMP(SString S,SString T){
int i=1,j=1;
int next[T.length+1];
get_next(T,next);
printf("next:");
for(int k=1;k<=T.length;k++){
printf("%d ",next[k]);
}
printf("\n");
int nextval[T.length+1];
nextval[1]=0;
for(int j=2;j<=T.length;j++){
if(T.ch[next[j]] == T.ch[j]){
nextval[j]=nextval[next[j]];
}else{
nextval[j]=next[j];
}
}
printf("nextval:");
for(int k=1;k<=T.length;k++){
printf("%d ",nextval[k]);
}
printf("\n");
while(i<=S.length && j<=T.length){
if(j==0 || S.ch[i]==T.ch[j]){
++i;
++j;
}else{
j=next[j];
}
}
if(j>T.length){
return i-T.length;
}else{
return 0;
}
}
int main(){
SString S; //主串
char ch[]={"aaaaaaabaa"};
StringAssign(S,ch);
printf("主串:");
ShowString(S);
SString T; //子串
char cl[]={"aaaab"};
StringAssign(T,cl);
printf("字串:");
ShowString(T);
int i=Index_KMP(S,T);
printf("index is:%d",i);
}
结果:
len=10
主串:aaaaaaabaa
len=5
字串:aaaab
next:0 1 2 3 4
nextval:0 0 0 0 4
index is:4