数据结构之串

串是由零个或多个字符组成的有限序列。
记为:s=“a1a2…an” (n≥0)
其中,s是串的名,用双引号括起来的字符序列是串的值。
(1) 串的长度:串中字符的数目n。
(2) 空串(Null string):长度为零的串。
(3) 子串:串中任意个连续的字符组成的子序列。
(4) 主串:包含子串的串相应地称为主串。
(5) 串相等:只有当两个串的长度相等,并且各个对应位置的字符都相等,称两串相等。
(6) 空格串(空白串)(blank string): 由一个或多个空格组成的串。要和“空串”区别,空格串有长度就是空格的个数。
串和一般线性表的区别:
(1) 串数据对象约束为字符集。
(2) 基本操作的对象不同,线性表以“单个元素”
为操作对象;串以“串的整体”为操作对象,操作的一般都是子串。
在这里插入图片描述结论:采用普通链表存储字符串,存储密度非常低,浪费空间严重。
解决办法:一个结点存储多个字符。这就是串的块链存储。
模式匹配简单算法

在这里插入图片描述
在这里插入图片描述
模式匹配KMP算法
KMP算法的思想:
主串指针不回溯,模式串向后滑动至某个位置上
在这里插入图片描述
利用KMP算法求next的值:
ababaaababaa 字符串长度为12,则next[12]数组长度也为12
规定:next[1]=0,next[2]=1;
求next[3],取ab,前缀后缀不相等,所以next[2]=1;
求next[4],取aba,a和a关于b对称,前缀a和后缀a相等,next[3]=1+1=2;
求next[5],取abab,ab和ab相等,所以,next[5]=2+1=3;
求next[6],取ababa,aba和aba相等,next[6]=3+1=4;
求next[7],取ababaa,s[1]=a和s[6]=a相等,next[7]=1+1=2;
求next[8],取ababaaa,s[1]=a和s[7]=a相等,next[8]=1+1=2;
求next[9],取ababaaab,s[1]s[2]和s[7]s[8]相等,next[9]=2+1=3;
求next[10],取ababaaaba,s[1]s[2]s[3]和s[7]s[8]s[9]相等,next[10]=3+1=4;
求next[11],取ababaaabab,s[1]s[2]s[3]s[4]和s[7]s[8]s[9]s[10]相等,next[11]=4+1=5;
求next[12],取ababaaababa,s[1]s[2]s[3]s[4]s[5]和s[7]s[8]s[9]s[10]s[11]相等,next[12]=5+1=6;
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h> 
#define OVERFLOW -1 
#define OK 1 
#define ERROR 0 
#define TRUE 1 
#define FALSE 0
#define MAXStrlen 255 //用户可以在255以内定义最大串长
typedef unsigned char Sstring[MAXStrlen + 1];//0号单元存放串的长度 顺序存储C语言实现 
typedef struct { //堆分配存储 
	char* ch; //若非空串,则按串长分配存储区,否则,ch为NULL
	int length;//串长度
}HString; 
#define ChunkSize 80 //串的块链存储  
typedef struct Chunk{ //节点结构 
	char ch[ChunkSize]; 
	struct Chunk* next; 
}Chunk;
typedef struct { //串的链表结构 
	Chunk* head, * tail; //串的头和尾指针 
	int curlen;//当前串长度
}LString; //若主串S中存在和串T值相同的子串返回它在主串S中第pos个字符之后第一次出现的位置;否则函数 值为0. 
int Index(char s[], char t[], int pos,int lens,int lent)
{  int i = pos;
   int j = 1;
   while (i<=lens&&j<=lent)
   { 
	   printf("%c %c\n", *(s + i), *(t + j));
	   if (*(s+i) == *(t+j))//继续比较后面的字符 
		{ ++i; ++j;} 
	 else { 
	   i = i - j+2;//指针回退,重新开始匹配
	   j = 1; //因为本来串的第一个位置存长度的,所以返回t[1]
	 }
   } 
   if (j > lent) return i - lent;
   return 0;
}
 void Get_Next(char t[], int next[],int lent) 
{ 
	int i = 1, j = 0; 
	*next = 0; *(next + 1) = 0; 
	while (i < lent) 
	{ 
		if(j==0||*(t+i)==*(t+j)) 
		{ 
			++i; ++j;
			*(next+i) = j;
		} 
		j = *(next+j);//***
	} 
 }
 int Index_KMP(char s[], char t[], int pos,int lens,int lent)
 { 
	 int i = pos; int j = 1; 
	 int next[MAXStrlen]; 
	 Get_Next(s, next,lens);
	 while (i<=lens&& j <= lent) 
	 { 
		 if (j == 0 || *(s + i) == *(t + j)) { i++; j++; } 
		 else 
		 {
			 j = next[j];//i不变,j后退
		 }
	 } 
	 if (j > lent) //匹配成功
	 return i - lent;
	 return 0; //f返回不成功的标志 
 } 
 int main() { 
	 char s[] = { 'o','a','b','a','b','a','a','a','b','a','b','a' };
	 char t[] = { 'o','a','a','a'};
	 int pos = 1;
	 printf("%d\n",Index_KMP(s,t,pos,11,3)); 
	 return 0;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值