串的定义,实现和模式匹配

串的相关概念及操作

串的定义

串:是由零个或多个字符组成的有限序列。
空串:不包含任何字符的串称为空串。
子串:串中任意个连续的字符组成的子序列称为该串的子串。
空格串:由一个或多个空格组成的串称为空格串(空格串不是空串,其长度为串中空格字符的个数)。

串的存储结构

定长顺序存储表示

类似于线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。在串的顺序存储结构中,为每个串变量分配一个固定长度的存储区,即定长数组。

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

堆分配存储表示

堆分配存储表示仍然以一组地址连续的存储单元存放串值得字符序列,但它们得存储空间是在执行过程中动态分配得到的。

typedef struct{char *ch;  //按串长分配存储去,ch指向串的基地址int length;  //串的长度
}HString;

块链存储表示

由于串的特殊性(每个元素只有一个字符),在具体实现时,每个结点既可以存放一个字符,也可以存放多个字符。
每个结点称为块,整个链表称为块链结构。
在这里插入图片描述

串的相关操作

  • StrAssign(&T, chars): 赋值操作。把串T赋值为 chars
  • Strcopy(&T, S):复制操作。由串S复制得到串T。
  • StrEmpty(S): 判空操作。若S为空串,则返回TRUE,否则返回 FALSE
  • StrCompare(S,T): 比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
  • StrEngth(S): 求串长。返回串S的元素个数
  • Substring(&Sub,S,pos,1en):求子串。用Sub返回串S的第pos个字符起长度为len的子串
  • Concat(&T,S1,S2): 串联接。用T返回由S1和S2联接而成的新串。
  • Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0
  • Clearstring(&S):清空操作。将S清为空串 Destroystring(&S): 销毁串。将串S销毁
  • 不同的高级语言对串的基本操作集可以有不同的定义方法。在上述定义的操作中,串赋值StrAssign、串比较 StrCompare、求串长Strength、串联接 Concat及求子串Substring五种操作构成串类型的最小操作子集,即这些操作不可能利用其他串操作来实现;反之,其他串操作(除串清除Clearstring和串销毁 Destroystring外)均可在该最小操作子集上实现。 例如,可利用判等、求串长和求子串等操作实现定位函数 Index(S,T)。

串的模式匹配

简单的模式匹配算法

子串的定位操作通常称为串的模式匹配,它求的是子串(常称模式串)在主串中的位置。这里采用静态顺序存储结构,给出一种不依赖于其他串操作的暴力匹配算法.

算法思想

从主串的第一个字符起,与子串的第一个字符比较,若相等,则继续逐个比较后续字符;若不相等,则从主串的下一个字符起,重新和子串的字符比较,以此类推。
缺点:当某些子串与模式串能部分匹配时,主串的扫描指针经常回溯,导致时间开销大
暴力模式匹配算法的最坏时间复杂度为 O(nm) 其中 n 和 m 分别为主串和子串的长度。

完整代码

#include<stdio.h>
#include<string.h>
#define MAXSIZE 255      //预定于最大串长为255typedef struct{char ch[MAXSIZE];    //每个分量存储一个字符int length;          //串的实际长度
} SString;//初始化串 
void InitString(SString &S, SString &T) {for (int i = 0; i < MAXSIZE; ++i) {S.ch[i] = '\0';T.ch[i] = '\0';}S.length = 0;T.length = 0;
}int Index(SString S, SString T){int i = 0, j = 0;while(i < S.length && j < T.length){if(S.ch[i] == T.ch[j]){++i; ++j;	//继续比较后继字符}else{//指针后退重新开始匹配i = i-j+1;j = 0;}}if(j >= T.length){return i - T.length;}else{return 0;}
}int main(){SString S,T;InitString(S, T);//初始化串 char a[15] = {'h','o','l','l','o','h','e','l','l','o','h','l','l','e','o'};strcpy(S.ch, a);    // a数组复制给S的数组	S.length = 15;for(int i = 0;i < S.length;i++){//打印S的数组printf("%2c", S.ch[i]);}printf("\n");char b[5] = {'h','e','l','l','o'};strcpy(T.ch, b);// b数组复制给S的数组	T.length = 5;for(int i = 0;i < T.length;i++){//打印T的数组printf("%2c", T.ch[i]);}printf("\n");int flag = Index(S, T);printf("%d\n", flag);if(flag){printf("find it and the number is %d\n", flag);}else{printf("cannot find!\n"); } return 0;
} 

KMP算法

求解next数组

//计算next数组 
void Getnext(SString T,  int *next) 
{for(int j = 0; j < 5; j++ ){next[j] = 0;} int i,k;i=0;k=-1;next[0]=-1;while (i<T.length - 1)  /* 此处T[0]表示串T的长度 */{if(k==-1 || T.ch[i]== T.ch[k]) {i++;  k++;  next[i] = k;} else k= next[k];	/* 若字符不相同,则k值回溯 */}for(int j = 0; j < 5; j++ ){printf("%2d", next[j] + 1);} 
}

KMP匹配算法

//KMP算法的匹配过程
int IndexKMP(SString S, SString T, int *next){int i = 0;int j = 0;while(i < S.length && j < T.length){if(j == -1 || S.ch[i] == T.ch[j]){++i; ++j;}else{j = next[j];}}if(j > T.length -1)return i - j + 1;elsereturn 0;
}

KMP完整代码

目标串:a b a b c a b c a c b a b
模式串:a b c a c

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Maxsize 255typedef struct{char ch[Maxsize];//存放字符 int length;//串的实际长度 
}SString;//初始化
void InitString(SString &S,SString &T){for(int i = 0; i < Maxsize; i++){S.ch[i] = '\0';T.ch[i] = '\0';}S.length = 0;T.length = 0;} //计算next数组 
void Getnext(SString T,  int *next) 
{for(int j = 0; j < 5; j++ ){next[j] = 0;} int i,k;i=0;k=-1;next[0]=-1;while (i<T.length - 1)  /* 此处T[0]表示串T的长度 */{if(k==-1 || T.ch[i]== T.ch[k]) {i++;  k++;  next[i] = k;} else k= next[k];	/* 若字符不相同,则k值回溯 */}for(int j = 0; j < 5; j++ ){printf("%2d", next[j]);} 
}//打印字符数组 
void PrintString(SString S, SString T){for(int i = 0;i < S.length;i++){printf("%2c", S.ch[i]);}printf("\n");for(int i = 0;i < T.length;i++){printf("%2c", T.ch[i]);}printf("\n");
}//KMP算法的匹配过程
int IndexKMP(SString S, SString T, int *next){int i = 0;int j = 0;while(i < S.length && j < T.length){if(j == -1 || S.ch[i] == T.ch[j]){++i; ++j;}else{j = next[j];}}if(j > T.length -1)return i - j + 1;elsereturn 0;
}int main(){SString S, T;InitString(S, T); //初始化 char a[13] = {'a','b','a','b','c','a','b','c','a','c','b','a','b'};char b[5] = {'a','b','c','a','c'};strcpy(S.ch, a);//将a数组中的字符复制到S数组中 S.length = 13;strcpy(T.ch, b);//将b数组中的字符复制到T数组中 T.length = 5;PrintString(S, T);//打印字符串 int *next = (int*)malloc(6*sizeof(int));Getnext(T, next);//求解next数组printf("\n");int index = IndexKMP(S, T, next);//KMP匹配算法 if(index){printf("The same string is %d", index);}else{printf("The same string cannot find");}return 0;
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/97448.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac常见问题(五) Mac 无法开机

在mac的使用过程中难免会碰到这样或者那样的问题&#xff0c;本期为您带来Mac 无法开机怎么进行操作。 1、按下 Mac 上的电源按钮。每台 Mac 电脑都有一个电源按钮&#xff0c;通常标有电源符号 。然后检查有没有通电迹象&#xff0c;例如&#xff1a; 发声&#xff0c;例如由风…

【Unity3D赛车游戏优化篇】【八】汽车实现镜头的流畅跟随,以及不同角度的切换

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

Shell脚本练习——系统应用相关

显示系统信息 [rootwenzi data]#cat systemInfo.sh #/bin/bash RED"\E[1;31m" GREEN"\E[1;32m" END"\E[0m" echo -e "$GREEN----------------------Host systeminfo--------------------$END" echo -e "HOSTNAME: $REDho…

Python实现Word、Excel、PPT批量转为PDF

今天看见了一个有意思的脚本Python批量实现Word、EXCLE、PPT转PDF文件。 因为我平时word用的比较的多&#xff0c;所以深有体会&#xff0c;具体怎么实现的我们就不讨论了&#xff0c;因为这个去学了也没什么提升&#xff0c;不然也不会当作脚本了。这里我将其放入了pyzjr库中…

npm install依赖冲突解决办法

今天npm的时候发现报错&#xff0c;原来是依赖冲突了 npm后面加上这个指令就可以顺利的安装依赖了。问题主因就是不同开发用了不同版本node导致依赖版本不同&#xff0c;出现了成功冲突&#xff0c;这是段指令&#xff1b;它告诉npm忽略项目中引入的各个依赖模块之间依赖相同但…

[Rust GUI]0.10.0版本iced代码示例 - progress_bar

-1 字体支持 iced0.10.0 仅支持指定系统内置字体(用iced的默认字体是乱码) iced0.10.0 手动加载字体的功能已经砍了&#xff0c;想手动加载就用0.9.0版本&#xff0c;文档0.9.0版本 想显示中文则需要运行在一个自带字体的Windows系统上。而且这个字体最好不要钱。 (Windows闲着…

Prometheus + grafana 的监控平台部署

一、Prometheus安装 tar -zxvf prometheus-2.44.0.linux-amd64.tar.gz -C /opt/module/ sudo chown -R bigdata:bigdata /opt/module/prometheus-2.44.0.linux-amd64 mv /opt/module/prometheus-2.44.0.linux-amd64 /opt/module/prometheus-2.44.0 ln -s /opt/module/promethe…

【传输层】TCP -- 三次握手四次挥手 | 可靠性与提高性能策略

超时重传机制连接管理机制三次握手四次挥手滑动窗口拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结基于TCP应用层协议理解 listen 的第二个参数 超时重传机制 主机A发送数据给B之后&#xff0c;可能因为网络拥堵等原因&#xff0c;数据无法到达主机B&#xff1…

cocosCreator2.4.x 打包 ios ,xcode问题记录

Q&#xff1a;Uncaught ReferenceError: CC_PHYSICS_BUILTIN is not defined A&#xff1a;先clean build folder....&#xff0c;然后重新build Q&#xff1a;xcode 使用模拟器预览 报错 In /Library/Developer/Xcode/DerivedData/hello_world-djnvsdcqyfoqvdepilidvunfunto…

一文入门Web网站安全测试

文章目录 Web网页安全风险评估1. 数据泄漏2. 恶意软件传播3. 身份伪装和欺诈 测试Web网页的安全性常见方法和工具漏洞扫描器手动漏洞测试漏洞利用工具Web应用程序防火墙&#xff08;WAF&#xff09;测试渗透测试代码审查社会工程学测试 推荐阅读 Web网页安全风险评估 越来越多…

uniapp 处理 分页请求

我的需求是手机上一个动态滚动列表&#xff0c;下拉到底部时&#xff0c;触发分页数据请求 uniapp上处理分页解决方案 主要看你是如何写出滚动条的。我想到的目前有三种 &#xff08;1&#xff09;页面滚动&#xff1a;直接使用onReachBottom方法&#xff0c;可以监听到达底部…

电脑录屏卡顿是什么原因 电脑录屏卡顿怎么变流畅

大家在电脑录屏的时候可能会遇到卡顿的情况&#xff0c;其实造成电脑录屏卡顿的因素有很多&#xff0c;环境外部因素和软件内部因素都会对电脑产生影响&#xff0c;今天我们来解答电脑录屏卡顿是什么原因&#xff0c;电脑录屏卡顿怎么变流畅&#xff0c;一起来看看吧。 一、电脑…