csdn_spider/blog/ds19991999/原创-- 第四章 串.md

244 lines
5.0 KiB
Markdown
Raw Normal View History

2021-02-27 15:01:45 +00:00
# 原创
第四章 串
# 第四章 串
2024-07-03 09:49:47 +00:00
## 一、串数据类型的定义
2021-02-27 15:01:45 +00:00
2024-07-03 09:49:47 +00:00
### 1.定义和存储结构
2021-02-27 15:01:45 +00:00
```
char str[]="abcdef";
//定长顺序存储
typedef struct
{
char str[maxSize+1];//加1是为了多出一个用来存储'\0'作为结束标记
int length;
}Str;
//变长分配存储
typedef struct
{
char *ch;
int length;
}Str;
```
2024-07-03 09:49:47 +00:00
### 2.串的基本操作
2021-02-27 15:01:45 +00:00
```
//1.赋值
int strassign(Str& str,char* ch)
{
if(str.ch)free(str.ch) //释放原数组空间
int len=0;
char *c=ch; //c指向ch
while(*c) //求串的长度
{
++len;
++c;
}
if(len==0)
{
str.ch=NULL;
str.length=0;
return 1;
}
else
{
str.ch=(char*)malloc(sizeof(char)*(len+1));
if(str.ch==NULL)return 0;
else
{
c=ch;
for(int i=0;i<=len;++i,++c)str.ch[i]=*c;
str.length=len;
return 1;
}
}
}
//strassign(str,"cur input")
//2.取串的长度
int strlength(Str str)
{
return str.length;
}
//3.串比较操作
int strcompare(Str s1, Str s2)
{
for(int i;i<s1.length&&i<s2.length;++i)
{
if(s1.ch[i]!=s2.ch[i])return s1.ch[i]-s2.ch[i];
return s1.length-s2.length;
}
}
//4.串连接操作
int concat(Str &str, Str str1, Str str2)
{
//如果str不为空则释放str空间
//如果为空则返回0也就是不能进行串操作
if(str.ch)
{
free(str.ch);
str.ch=NULL;
}
str.ch=(char*)malloc(sizeof(char)*(str1.length+str2.length+1));
if(str.ch==NULL)return 0;
int i=0;
while(i<str1.length)
{
str.ch[i]=str1.ch[i];
++i;
}
int j;
while(j<=str2.length)
{
str.ch[i+j]=str2.ch[j];
++j;
}
str.length=str1.length+str2.length;
return 1;
}
//5.求子串操作
//从pos处开始长度为len的子串
int substring(Str& substr, Str str, ingt pos,int len)
{
if(pos<0||pos>=str.length||len<0||len>str.length-pos)return 0;
if(substr.ch)
{
free(substr.ch);
substr.ch=NULL;
}
if(len==0)
{
substr.ch=NULL;
substr.length=0;
return 1;
}
else
{
substr.ch=(char*)malloc(sizeof(char)*(len+1));
int i=pos;
int j=0;
while(i<pos+len)
{
substr.ch[j]=str.ch[i];
++i;
++j;
}
substr.ch[j]='\0';
sunstr.length=len;
return 1;
}
}
//6.串清空操作
int clearstring(Str& str)
{
if(str.ch)
{
free(str.ch);
str.ch=NULL;
}
str.length=0;
return 1;
}
```
2024-07-03 09:49:47 +00:00
## 二、串的模式匹配算法
2021-02-27 15:01:45 +00:00
2024-07-03 09:49:47 +00:00
### 1.简单模式匹配算法
2021-02-27 15:01:45 +00:00
```
//对一个串中的定位操作称为串的模式匹配
//其中串中字符存放在1-length的位置上
int index(Str str,Str substr)
{
int i=1,j=1,k=i;
while(i<=str.length&&j<=str.length)
{
if(str.ch[i]==substr.ch[j])
{
++i;
++j;
}
else
{
j=1;
i=++k;
}
}
if(j>substr.length)return k;
else return 0;
}
```
2024-07-03 09:49:47 +00:00
### 2.KMP算法
2021-02-27 15:01:45 +00:00
```
//思路每当发生模式串不匹配的情况先找出发生不匹配的字符pj,取其子串F=p1p2p3...Pj-1
//将模式串后移使F最先发生前部FL和后部FR相重合的位置即模式串后移的目标位置
//即j指向的F前后重合的子串的长度+1FL和FR的长度加1,可以定义一个next[j]数组,取j=1~m
//m为模式串长度表示模式串中第j个字符发生不匹配时应从next[j]处的字符开始重新发生与主串比较
//求next数组
//next[j]已知t为当前F最长相等前后缀长度即FL和FR的长度next[j]=t
//当pj=pt则next[j+1]=t+1;
//当pj!=pt,则t=next[t];
void getnext(Str substr, int next[])
{
int j=1,t=0;next[1]=0;
while(j<substr.length)
{
if(t==0||substr.ch[i]==substr.ch[t])next[++j]=++t;
else t=next[t];
}
}
//得到next数组之后可以将简单算法改进成著名的KMP算法
int KMP(Str str, Str substr, int next[])
{
//假设从下标为1开始存储的字符
int i=1, j=1;
while(i<=str.length&&j<=substr.length)
{
if(j==0||str.ch[i]==substr.ch[j])
{
++i;
++j;
}
else j=next[j];
}
if(j>substr.length)retrun i-substr.length;
else return 0;
}
```
2024-07-03 09:49:47 +00:00
### 3.KMP算法的改进
2021-02-27 15:01:45 +00:00
```
//当j=1时nextva[j]=0,作为特殊标记
//pj!=pk时nextval[j]=next[j]=k;
//pj=pk时nextval[j]=nextval[next[j]]=nextval[k];
void getnextval(Str substr,int nextval[])
{
int i=1,j=0;
nextval[1]=0;
while(i<substr.length)
{
if(j==0||substr.ch[i]==substr.ch[j])
{
++i;
++j;
// 加了这两句
if(substr.ch[i]!=substr.ch[j])nextval[i]=j;
else nextval[i]=nextval[j];
}
else j=nextval[j];
}
}
```