串是零个或多个字符组成的有限序列。串中所包含的字符个数为该串的长度。串中任意个连续的字符组成的子序列称为该串的子串。包含子串的相应地称为主串。通常,把子串在主串中第一次出现时,子串的第一次字符在主串中的序号,定义为子串在主串中的序号。
建立
#include<stdio.h>
#define SIZE 100
typedef struct
{
char data[SIZE];
int len;
} String;
结构体中包含一个字符串数组和串长。
初始化
void Init(String &s)
{s.len=0;}
令串长为0。
基本操作
1.入串
void Input(String &s,char *ps)
{
while(*ps)
{
s.data[++s.len]=*ps;
ps++;
}
}
参数中定义了一个指针,指针刚开始指向定义的字符数组中第一个元素,依次赋值给
结构体中的数组,再完成指针的移动。
注意此时的++s.len 使该字符串有了一个头结点不存放任何值。
2.遍历
void Display(String s)
{
for(int i=1;i<=s.len;i++)
putchar(s.data[i]);
}
从首结点开始遍历串中的元素。
判断串相等处的下标
1.BF算法
int BF(String s,String t){
int i=1;
int j=1;
while(i<=s.len&&j<=t.len)
if(s.data[i]==t.data[j]){
i++;
j++;
}
else{
i=i-j+2;
j=1;
}
if(j>t.len)
return i-j+1;
return -1;
}
此算法为暴力算法,定义的两个指针每次匹配都需返回。
两个字符串均从头开始匹配,若值相等则指针后移,否则j回到初始位置,i回到i-j+2的位置。直到j超过该字符串的长度,证明串匹配成功,此时i-j+1的位置就是串相等处的下标。
否则匹配失败返回-1。
2.KMP算法
void GetNext(String s,int *next){
int i=1,j=0;
next[1]=0;
while(i<=s.len){
if(j==0||s.data[i]==s.data[j]){
i++;
j++;
next[i]=j;
}
else j=next[j];
}
}
int KMP(String s,String t){
int i=1;
int j=1;
int next[SIZE];
GetNext(t,next);
while(i<=s.len&&j<=t.len)
if(j==0||s.data[i]==t.data[j]){
i++;
j++;
}
else
j=next[j];
if(j>t.len)
return i-j+1;
return -1;
}
此算法不需要对主串中的i值进行返回,只通过对j指针的返回完成串的匹配。
首先对要判断的字串进行next求值,再返回所求的下标。
代码测试
int main(){
char ch1[]="20200305016",ch2[]="0030";
String s,t;
Init(s);Init(t);
Input(s,ch1);Input(t,ch2);
Display(s);printf("\n");
Display(t);printf("\n");
printf("%d,%d",BF(s,t),KMP(s,t));
return 0;
}
广义表
线性表是一种特殊的广义表,但广义表不一定是线性表。
广义表中的基本操作