串的逻辑结构和线性表极为相似,区别仅在于串的数据对象约束为字符集。这里主要介绍一下串的数据类型定义,存储结构,以及串的模式匹配算法——BF 算法和 KMP 算法。

1.串的数据类型定义

数据对象

  • D = { ai | ai ∈ CharacterSet, i = 1, 2, …, n, n ≥ 0 }

1.1 数据关系

  • R1 = { < ai, aj > | i < j, ai, aj ∈ D, i = 2, …, n }

1.2 基本操作

操作名称 初始条件 操作结果
StrAssign(&T, chars) chars 是字符串常量。 生成一个其值等于 chars 的串 T。
StrCopy(&T, S) 串 S 存在。 由串 S 复制得串 T。
StrEmpty(S) 串 S 存在。 若 S 为空串,则返回 true;否则返回 false。
StrCompare(S, T) 串 S 和 T 存在。 若 S > T, 则返回值 > 0; 若 S = T, 则返回值 = 0; 若 S < T, 则返回值 < 0。
StrLength(S) 串 S 存在。 返回 S 的元素个数,称为串的长度。
ClearString(&S) 串 S 存在。 将 S 清为空串。
Concat(&T, S1, S2) 串 S1 和 S2 存在。 用 T 返回由 S1 和 S2 连接而成的新串。
SubString(&Sub, S, pos, len) 串 S 存在,1 ≤ pos ≤ StrLength(S) 且 0 ≤ len ≤ StrLength(S) - pos + 1。 用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串。
Index(S, T, pos) 串 S 和 T 存在,T 是非空串,1 ≤ pos ≤ StrLength(S)。 若主串 S 中存在和串 T 值相同的子串,则返回它在主串 S 中第 pos 个字符之后第一次出现的位置;否则函数值为 0。
Replace(&S, T, V) 串 S, T 和 V 存在,T 是非空串。 用 V 替换主串 S 中出现的所有与 T 相等的不重叠的子串。
StrInsert(&S, pos, T) 串 S 和 T 存在,1 ≤ pos ≤ StrLength(S) + 1。 在串 S 的第 pos 个字符之前插入串 T。
StrDelete(&S, pos, len) 串 S 存在,1 ≤ pos ≤ StrLength(S) - len + 1。 从串 S 中删除第 pos 个字符起长度为 len 的子串。
DestroyString(&S) 串 S 存在。 串 S 被销毁。

2.串的存储结构

2.1 串的顺序存储

// 串的顺序存储结构
#define Max_Size 255 //串的最大长度
typedef struct String{
char ch[Max_Size+1];
int length;
}SString;

其中,Max_Size 表示串的最大长度,ch 是存储字符串的一维数组,每个分量存储一个字符,length 表示字符串的当前长度。为了符合习惯,一般将下标为 0 的数组闲置不用,尽量从 1 开始。

2.2 串的链式存储

// 串的链式存储
typedef struct LNode{
char *ch;
struct LNode *next;
}LinkList; typedef struct {
LinkList *head,*tatial; //串的头尾指针
int length;
}LString;

顺序串的插入和删除操作不方便,需要移动大量的字符。因此, 可采用单链表方式存储串。

3.串的模式匹配算法

子串的定位运算通常称为串的模式匹配或串匹配。此运算的应用非常广泛,比如在搜索引擎、拼写检查、语言翻译、数据压缩等应用中, 都需要进行串匹配。
串的模式匹配设有两个字符串 S 和 T, 设 S 为主串,也称正文串;设 T 为子串,也称为模式。在主串 S 中查找与模式 T 相匹配的子串,如果匹配成功, 确定相匹配的子串中的第一个字符在主串 S 中出现的位置。
著名的模式匹配算法有 BF 算法和 KMP 算法,下面详细介绍这两种算法。

3.1BF 算法

BF 算法是经典的暴力解法,子串 T 与 S 逐个匹配,相同就往后走,不相同就回溯。这个算法最好情况下时间复杂度为 O(n+m),最坏情况下为 O(m*n)。具体代码如下

// BF算法
int Index_BF(SString S, SString T, int pos){
// 返回模式T在主串s中第pos个字符开始第一次出现的位置。若不存在, 则返回值为0
int i = pos;
int 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; //匹配成功
}
return 0;
}

3.2KMP 算法

KMP 算法可以在 O(n+m)的时间数量级上完成串的模式匹配操作。其改进在千:每当一趟匹配过程中出现字符比较不等时,不需回溯 l 指针,而是利用已经得到的”部分匹配" 的结果将模式向右"滑动“ 尽可能远的一段距离后,继续进行比较。

// 获取next数组
void Get_Next(SString T, int next[]){
int i = 1;
next[1] = 0;
int j = 0;
while (i < T.length){
if(j == 0 || T.ch[i] == T.ch[j]){
i++;
j++;
next[i] = j;
}else{
j = next[j];
}
}
} //KMP算法
int Index_KMP(SString S, SString T, int pos, int next){
int i = pos;
int j = 1;
while (i <= S.length && j <= T.length){
if(S.ch[i] == T.ch[j]){
i++;
j++;
}
else{
j = next[j];
}
}
if(j > T.length){
return i - S.length;
}
return -1;
}

前面定义的 next 函数在某些情况下尚有缺陷;例如模式"aaaab" 在和主串"aaabaaaab"匹配时,当 i = 4 、j= 4 时 s.ch [ 4] -:t:- t.ch [ 4] , 由 next(j) 的指示还需进行 i = 4 、j= 3, i = 4 、j= 2, i = 4 、j=l 这 3 次比较。因此,需要我们对 next 进行修正。

// 修正next数组
void Get_Nextval(SString T, int nextval[]){
int i = 1;
nextval[0] = 0;
int j = 0;
while (j <= T.length){
if(j == 0 || T.ch[i] == T.ch[j]){
i++;
j++;
if(T.ch[i] == T.ch[j]){
nextval[i] = nextval[j];
}
else{
nextval[i] = j;
}
}
else{
j = nextval[j];
}
}
}

以上就是串的全部内容,如有错误请联系 QQ:303623518

串(C语言实现)的更多相关文章

  1. 010-字符串-C语言笔记

    010-字符串-C语言笔记 学习目标 1.[掌握]二维数组的声明和初始化 2.[掌握]遍历二维数组 3.[掌握]二维数组在内存中的存储 4.[掌握]二维数组与函数 5.[掌握]字符串 一.二维数组的声 ...

  2. 周期串(JAVA语言)

    package 第三章习题; /*  * 如果一个字符可以由某个长度为k的字符串重复多次得到,则称该串以k为周期.  * 例如:abcabcabcabc 以3为周期(注意:它也以6和12为周期)  * ...

  3. 自动机理论、语言和计算导论 by John E. Hopcroft

    计算理论是计算机应用的基础,理论和应用缺一而不可. ---- 目录 ---- C01 自动机 C02 有穷自动机 C03 正则表达式与正则语言 C04 正则语言的性质 C05 上下文无关文法及上下文无 ...

  4. 【接口时序】2、Verilog实现流水灯及与C语言的对比

    一. 软件平台与硬件平台 软件平台: 1.操作系统:Windows-8.1 2.开发套件:ISE14.7 3.仿真工具:ModelSim-10.4-SE 硬件平台: 1.FPGA型号:XC6SLX45 ...

  5. 【转】iOS多语言本地化(国际化)设置

    原文网址:http://www.jianshu.com/p/2b7743ae9c90 讨论的iOS应用中的多语言设置,Ok 一般是两种情况: 1.根据当前设备语言自动切换显示 2.在应用中可进行语言设 ...

  6. Compiler Theory(编译原理)、词法/语法/AST/中间代码优化在Webshell检测上的应用

    catalog . 引论 . 构建一个编译器的相关科学 . 程序设计语言基础 . 一个简单的语法制导翻译器 . 简单表达式的翻译器(源代码示例) . 词法分析 . 生成中间代码 . 词法分析器的实现 ...

  7. MPI简介

    什么是MPI: MPI是一个库,而不是一门语言.但是按照并行语言的分类,可以把FORTRAN+MPI或者C+MPI看作是一种在原来串行语言基础上扩展后得到的并行语言.MPI库可以被FORTRAN77/ ...

  8. Android jni 编程1(对基本类型字符串的操作)

    最近一直在学安卓的jni,主要参考的是黑马程序员的视频教程,讲的确实不错. 那就自己总结一下吧,算是对学习的复习. 这篇博客也主要参考了这位博主:http://www.cnblogs.com/acti ...

  9. win 10 在vs2017下对mpi的安装以及认识

    这里我先对MPI进行一下简单的介绍,MPI的全称是Message Passing Interface,即消息传递接口. 它并不是一门语言,而是一个库,我们可以用Fortran.C.C++结合MPI提供 ...

  10. mpi4python

    转载:https://zhuanlan.zhihu.com/p/25332041 前言 在高性能计算的项目中我们通常都会使用效率更高的编译型的语言例如C.C++.Fortran等,但是由于Python ...

随机推荐

  1. python语言版(代码):计算百分数的概率单位

    相关资料: [转载]百分数的概率单位变换--解惑:概率确实没有单位但是数学里面确实有"概率单位"这个词 百分比与概率单位对照表 https://www.docin.com/p-22 ...

  2. 神经网络之卷积篇:详解Padding

    详解Padding 为了构建深度神经网络,需要学会使用的一个基本的卷积操作就是padding,让来看看它是如何工作的. 如果用一个3×3的过滤器卷积一个6×6的图像,最后会得到一个4×4的输出,也就是 ...

  3. Dijkstra单源最短路模板

    struct DIJ { using i64 = long long; using PII = pair<i64, i64>; vector<i64> dis; vector& ...

  4. OpenVino快速落地部署教程

    OpenVino快速落地部署教程 Openvino是由Intel开发的专门用于优化和部署人工智能推理的半开源的工具包,主要用于对深度推理做优化.本教程适用于Yolov5-7.0,直接跑Yolov5为6 ...

  5. 7.22-27MY&MS&ORA等SQL数据库提权

    7.22-27MY&MS&ORA等SQL数据库提权 思路:在利用系统溢出漏洞无果情况下,可以采用数据库提权: 前提:数据库服务开启,且获得数据库最高权限账号密码:除Access数据库外 ...

  6. netcore高级知识点,内存对齐,原理与示例

    最近几年一直从事物联网开发,与硬件打交道越来越多,发现越接近底层开发对性能的追求越高,毕竟硬件资源相对上层应用来实在是太缺乏了.今天想和大家一起分享关于C#中的内存对齐,希望通过理解和优化内存对齐,可 ...

  7. ARC119F 题解

    前言 ARC119F 好厉害,是没见过的自动机 DP. 正文 [1] 分析 主要分析一下为什么这么写. [2] 状态设计 [3] 自动机状态转移 感觉状态设计中最难的就是如何处理带 \(O\) 的. ...

  8. 1. Two Sum Go实现

    在数组中找到 2 个数之和等于给定值的数字,结果返回 2 个数字在数组中的下标. 1. 解法1 时间复杂度 O(n^2) 直接两次遍历所有节点,进行求和比较 代码如下: func twoSum(num ...

  9. Razor 常用又容易忘记语法

    1. <text> 要写 text 可以用这个特殊 element @:&nbsp   @: 也是一个可以写 text 的方式 2. @Html.Raw($@"<s ...

  10. Go runtime 调度器精讲(六):非 main goroutine 运行

    原创文章,欢迎转载,转载请注明出处,谢谢. 0. 前言 在 Go runtime 调度器精讲(三):main goroutine 创建 介绍了 main goroutine 的创建,文中我们说 mai ...