串的逻辑结构和线性表极为相似,区别仅在于串的数据对象约束为字符集。这里主要介绍一下串的数据类型定义,存储结构,以及串的模式匹配算法——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. &times被替换成x 的解决办法

    今天写代码遇到一个很有趣的问题: 在php中使用echo 输出url的时候当url中包含&times字段时就会被html直接解析成 x (乘号)这样一来我返回的地址就不能正常访问url了: 解 ...

  2. 9组-Beta冲刺-4/5

    一.基本情况(15分) 队名:不行就摆了吧 组长博客:9组-Beta冲刺-4/5 GitHub链接:https://github.com/miaohengming/studynote/tree/mai ...

  3. 8. 从0学ARM-内联汇编、混合汇编、ATPCS规则

    一.gcc 内联汇编 内联汇编即在C中直接使用汇编语句进行编程,使程序可以在C程序中实现C语言不能完成的一些工作,例如,在下面几种情况中必须使用内联汇编或嵌入型汇编. 程序中使用饱和算术运算(Satu ...

  4. k8s获取集群内所有在使用镜像

    kubectl get pods --all-namespaces -o jsonpath="{..image}" | tr -s '[[:space:]]' ' ' | sort ...

  5. 关于centos7下所有指令失效

    起因: 疑似宝塔更新修复后,本地所有环境变量集体不生效 问题环境 xshell环境下ssh连接 问题描述: - bash: xxx not fund - 环境变量无法保存 - 所有的保存方式都是临时生 ...

  6. P2P 下载入门

    基本概念 直链下载: https://file-examples.com/wp-content/storage/2017/04/file_example_MP4_480_1_5MG.mp4 直链就是一 ...

  7. Redis高可用方案:使用Keepalived实现主备双活

    注意:请确保已经安装Redis和keepalived,本文不在介绍如何安装. 1.使用版本说明 Redis版本:5.0.2 Keepalived版本:1.3.5 Linux 版本:Centos7.9 ...

  8. MRI roi图像合并

    笔记来源:MRI roi的图像合并 dpabi小工具_哔哩哔哩_bilibili 1. 如果几个图像的维度不一致,需要先进行reslice 1)如何看图像的维度 以软件MRIcron为例, windo ...

  9. LLM大模型基础知识学习总结

    大家好,我是Edison. 在这个已经被AI大模型包围的时代,不了解一点大模型的基础知识和相关概念,可能出去聊天都接不上话.刚好近期我也一直在用GPT和GitHub Copilot,也刚好对这些基础知 ...

  10. CSS & JS Effect – Image hover animation

    效果 效果来自: webflow 的一个模板 需求解释 有 3 给元素, 图片, overlay(黑影), link mouse enter 的时候, 图片要 zoom in. overlay 要 f ...