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

news2024/11/19 19:39:10

串的相关概念及操作

串的定义

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

串的存储结构

定长顺序存储表示

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

#define MAXSIZE 255      //预定于最大串长为255

typedef 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      //预定于最大串长为255

typedef 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;
		else
			return 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 255


typedef 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;
		else
			return 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.coloradmin.cn/o/971637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云原生Kubernetes:Kubeadm部署K8S单Master架构

目录 一、理论 1.kubeadm 2.Kubeadm部署K8S单Master架构 3.环境部署 4.所有节点安装docker 5.所有节点安装kubeadm&#xff0c;kubelet和kubectl 6.部署K8S集群 7.安装dashboard 8.安装Harbor私有仓库 9.内核参数优化方案 二、实验 1.Kubeadm部署K8S单Master架构 …

Windows环境下RabbitMQ下载安装

一、准备安装文件 1、下载Erlang 登录网站Downloads - Erlang/OTP&#xff0c;选择“Download Windows installer”&#xff0c;如下图所示&#xff1a; 弹出框中&#xff0c;选在下载保存地址&#xff0c;保存文件&#xff0c;如下图所示&#xff1a; 2、下载RabbitMQ 登录…

自动驾驶——估计预瞄轨迹YawRate

1.Introduction 在ADAS控制系统中&#xff0c;通常根据预瞄距离x去估计横向距离y&#xff0c;有如下关系&#xff1a; y a0 a1 x a2 * x^2 a3 * x^3 &#xff0c;那么现在有个需求&#xff0c;希望根据上述x和y的关系&#xff0c;去估计规划预瞄轨迹yawRate 2.How to es…

【Node.js】Node.js安装详细步骤和创建Express项目演示

Node.js是一个开源的、跨平台的JavaScript运行环境&#xff0c;用于在服务器端运行JavaScript代码。它提供了一个简单的API&#xff0c;可以用于开发各种网络和服务器应用程序。 以下是Node.js的安装和使用的详细步骤和代码示例&#xff1a; 1、下载Node.js 访问Node.js官方…

OPENCV实现图像查找

特征匹配+单应性矩阵 # -*- coding:utf-8 -*- """ 作者:794919561 日期:2023/9/4 """ import cv2 import numpy as np# 读图像 img1 = cv2.imread(F:\\learnOpenCV\\openCVLearning\\pictures\\chess

通过安装cpolar内网穿透在Kali上实现SSH远程连接的步骤指南

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过cpolar 内网穿透软件实现ssh 远程连接kali! 1. 启动kali ssh 服务 默认新安装的kali系统会关闭ssh 连接服务,我们通…

C++多态【上】

文章目录 1.多态的介绍1.1概念1.2分类 2.多态的实现2.1虚函数的介绍1.定义2.重写1.通常情况2.特例 2.2多态构成条件2.3破坏多态的情况1.父类没有虚函数 子类有对应虚函数重写2.父类有虚函数 子类没有重写对应虚函数 2.4虚析构和纯虚析构1.虚析构2.纯虚析构3.虚析构/纯虚析构存在…

vue项目配置MongoDB的增删改查操作

在Vue中配置MongoDB的增删改查操作&#xff0c;需要先安装mongoose模块来连接MongoDB数据库。 1. 在Vue项目的根目录中&#xff0c;使用命令行安装mongoose模块&#xff1a; npm install mongoose --save 2. 找到启动node的app.js文件&#xff08;我这里是在server文件中&…

Word转为PDF后图片模糊怎么办?Word转为PDF的技巧介绍

将Word文档转为PDF是我们日常办公和文档处理中常见的需求。PDF格式的优势在于跨平台兼容性、保留原始格式、文档保护以及方便共享和分发等方面。本文将探讨Word转为PDF后图片模糊怎么办?Word转为PDF的技巧有哪些?通过这些问题的答案&#xff0c;可以帮助您更好的利用文件转换…

Jenkins buildDescription 设置html格式及url

文章目录 1.首先安装插件2.更改配置3.接下来就可以在pipline里写脚本了 当然也可以插件方式配置示例1 脚本方式示例2 插件方式 搞了好多种方式都不成功后来发现是配置有问题&#xff0c;其实很简单&#xff0c;记录下也给想用此功能的朋友们一个示例&#xff0c;网上写的例子都…

蚂蚁集团SQLess 开源,与内部版有何区别?

当我们使用关系型数据库时&#xff0c;SQL 是联系起用户和数据库的一座桥梁。 SQL 是一种高度非过程化的语言&#xff0c;当我们在编写SQL 时&#xff0c;表达的是想要什么数据&#xff0c;而不是怎么获取数据。因此&#xff0c;我们往往更关心SQL 有没有满足业务逻辑&#xff…

【Windows 常用工具系列 11 -- 笔记本F5亮度调节关闭】

文章目录 笔记本 F 按键功能恢复 笔记本 F 按键功能恢复 使用笔记本在进行网页浏览时&#xff0c;本想使用F5刷新下网页&#xff0c;结果出现了亮度调节&#xff0c;如下图所示&#xff1a; 所以就在网上查询是否有解决这个问题的帖子&#xff0c;结果还真找到了&#xff1a;…

Sumo中Traci.trafficlight详解(上)

Sumo中Traci.trafficlight详解&#xff08;上&#xff09; 记录慢慢学习traci的每一天&#xff0c;希望也能帮到你 文章目录 Sumo中Traci.trafficlight详解&#xff08;上&#xff09;Traci.trafficlight信号灯参数讲解1.getAllProgramLogics(self,tlsID)2.getBlockingVehicle…

[uni-app]微信小程序隐私保护指引设置的处理记录

文章目录 微信幺蛾子资料搜集关键信息思路处理代码实现效果展示 微信幺蛾子 关于小程序隐私保护指引设置的公告 一切的起因就是上面这则公告. 2023年9月15日后 自2023年9月15日起&#xff0c;对于涉及处理用户个人信息的小程序开发者&#xff0c;微信要求&#xff0c;仅当开发…

电子班牌云平台系统——智慧校园管理工具,多媒体信息发布、走班排课、家校互通、物联控制、教务管理、考勤管理、素质评价、日常办公

电子班牌云平台源码&#xff0c;saas模式微服务架构 电子班牌是一款智慧校园管理工具&#xff0c;也是校园多媒体展示平台。智慧班牌融合了多媒体信息发布、走班排课、家校互通、物联控制、教务管理、考勤管理、素质评价、日常办公等一系列应用&#xff0c;是校园管理的现代化手…

React v6(仅支持函数组件,不支持类组件)与v5版本路由使用详情和区别(详细版)

1.路由安装(默认安装最新版本6.15.0) npm i react-router-dom 2.路由模式 有常用两种路由模式可选&#xff1a;HashRouter 和 BrowserRouter。 ①HashRouter&#xff1a;URL中采用的是hash(#)部分去创建路由。 ②BrowserRouter&#xff1a;URL采用真实的URL资源&#xff0c;…

接口自动化测试系列-excel管理测试用例

代码源码&#xff1a; 框架结构 核心代码 excel数据处理 from configureUtil.LogUtil import getlog logger getlog(targetNameHandleData) import xlrd from openpyxl import load_workbook,workbook from openpyxl.styles import Font, colors import openpyxl import o…

Docker-基础命令使用

文章目录 前言命令帮助命令执行示意图docker rundocker psdocker inspectdocker execdocker attachdocker stopdocker startdocker topdocker rmdocker prune参考说明 前言 本文主要介绍Docker基础命令的使用方法。 命令帮助 Docker命令获取帮助方法 # docker -h Flag shor…

网易低代码引擎Tango正式开源

一、Tango简介 Tango 是一个用于快速构建低代码平台的低代码设计器框架,借助 Tango 只需要数行代码就可以完成一个基本的低代码平台前端系统的搭建。Tango 低代码设计器直接读取前端项目的源代码,并以源代码为中心,执行和渲染前端视图,并为用户提供低代码可视化搭建能力,…