第四章 串



前言


1. 串的定义与实现

1.1 串的定义

串:由零个或多个字符组成的有限序列。
记为:
S=‘a1a2a3…an

S:串名
‘a1a2a3…an’:串的值
ai:可以是字母、数字、或其他字符。
n:串的长度

子串:串中任意多个连续的字符组成的子序列称为该串的子串。
字符在串中的位置:字符在串中序号称为字符在串中位置。
子串在主串中的位置:子串中的第一个字符在主串中的位置。
空格串:由一个或多个空格组成的串,其长度为串中空格字符的个数。
空串:无字符的串。

1.2 串的存储结构

1.2.1 定义顺序存储表示

#define MAXLEN 255 //预定义最大串长度为255
typedef struct {
	char ch[MAXLEN];//每个分量存储一个字符
	int length;//串的实际长度
}SString;

1.2.2 堆分配存储表示

堆分配存储表示
typedef struct {
	char *ch;//按串长度分配存储区,ch指向串的起始地址
	int length;//串的长度
}HString;

1.2.3块链存储表示

在这里插入图片描述

//每个节点一个字符
#define MaxSize 50
typedef char ElempType;
typedef struct {         // 链式队列结点
	ElempType chua;
	struct StringNode* next;
} StringNode;

在这里插入图片描述

//每个节点四个字符
typedef char ElempType;
typedef struct {         // 链式队列结点
	ElempType chua_0,chua_1, chua_2, chua_3;
	struct BStringNode* next;
} BStringNode;

1.3 串的基本操作

1.3.1 串类型的最小操作子集

注:串类型的最小操作子集为不可利用其他操作来实现。

  • StrAssign(&T,chars):赋值操作,把chars赋值给串T。
  • StrCompare(S,T):比较操作,若S>T,返回值>0;若S=T,返回值=0;若S<T,则返回值<0。
  • StrLength(S):求串长,返回串S的元素个数。 Concat(&T,S1,S2):串联接,用T返回由S1和S2联接而成的新串。
  • SubString(&Sub,S,pos,len):求子串,用Sub返回串S的第pos个字符起长度为len的子串。

1.3.2 其他操作

注:其他操作(除串销毁与串清楚)均可在串类型的最小操作子集上实现。

  • StrCopy(&T,S):复制操作,把串S赋值给串T。
  • StrEmpty(S):判空操作,若S为空串,返回TRUE,否则返回FALSE。
  • Index(S,T):定位操作,若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;负责函数值为零。
  • ClearString(&s):清空操作,将S清为空串。
  • DestoryString(&S):销毁串,将串S销毁。
    例如—定位函数Index(S,T)的实现:
int Index(String S, String T) {
	int i = 1; n = StrLength(S), m = StrLength(T);
	while (i <= n - m + 1) {
		SubString(sub, S, i, m);
		if (StrCompare(sub, T) != 0) ++i;
		else return i;//返回子串在主串中的位置
	}
	return 0;//S中不存在与T相等的子串	
}

2. 串的模式匹配

模式匹配:子串的定位操作通常称为串的模式匹配。

2.1 简单的模式匹配算法

2.1.1暴力匹配算法原理(BF法)

简单粗暴地拿一个串同另一个串中的字符一一比对,得到最终结果。

2.1.2实例

判断串 A(“abcac”)是否为串 B(“ababcabacabab”)子串的判断过程如下:
C语言中文网详细过程

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXLEN 255 //预定义最大串长度为255
typedef struct {
	char ch[MAXLEN];//每个分量存储一个字符
	int length;//串的实际长度
}SString;
int Index(SString S, SString T) {
	int i=1, j = 1;
	while (i <= S.length && j <= T.length) {
		if (S.ch[i] == T.ch[j]) {
			++i; //继续比较后继字符
			++j;	
		}
		else {
			i = i - j + 2; j = 1;//指针后退重新开始匹配
		}
	}
	if (j > T.length) return i - T.length;//返回子串位置
	else return 0;
}
//0ababcabcacbab
     //0abcac
int main() {
	SString S;
	scanf("%s", S.ch);//输入串0ababcacacbab;
	S.length=strlen(S.ch)-1;
	SString T;
	scanf("%s", T.ch);//输入串0abcac; 0ababcabcacbab 0abcac   
	T.length = strlen(T.ch)-1;
	int x= Index(S,T);
	if (x)
		printf("T串在S串中的位置为%d\n", x);
	else
		printf("T串中不包含于S串中\n");
}

输入:

0ababcabcacbab 0abcac

输出:

T串在S串中的位置为6

2.2 改进的模式匹配算法——KMP算法


2.2.1 字符串的前缀、后缀和部分匹配值

代码如下(示例):


2.2.2 KMP算法原理

代码如下(示例):


该处使用的url网络请求的数据。

2.3 KMP算法的进一步优化

在这里插入代码片

总结

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值