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

244 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 原创
第四章 串
# 第四章 串
## 一、串数据类型的定义
### 1.定义和存储结构
```
char str[]="abcdef";
//定长顺序存储
typedef struct
{
char str[maxSize+1];//加1是为了多出一个用来存储'\0'作为结束标记
int length;
}Str;
//变长分配存储
typedef struct
{
char *ch;
int length;
}Str;
```
### 2.串的基本操作
```
//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;
}
```
## 二、串的模式匹配算法
### 1.简单模式匹配算法
```
//对一个串中的定位操作称为串的模式匹配
//其中串中字符存放在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;
}
```
### 2.KMP算法
```
//思路每当发生模式串不匹配的情况先找出发生不匹配的字符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;
}
```
### 3.KMP算法的改进
```
//当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];
}
}
```