数据结构与算法之字符串

news2024/9/27 15:19:00

文章目录

  • 1.字符串定义
  • 2.串的几个基本概念
    • 2.1 空串:
    • 2.2空格串
    • 2.3子串
    • 2.4串相等
    • 2.5串比较
  • 3.串的基本操作(`此处以java为例`)
    • 3.1赋值操作StrAssign(s,t)
    • 3.2 连接操作 Concat(s,t)
    • 3.3求串长StrLength(s)
    • 3.4比较StrCompare(st)
    • 3.5 求子串_SubString(s,start,len)
  • 4.串的存储结构
    • 4.1 串的顺序存储结构
    • 4.2 串的链式存储
  • 5.朴素的模式匹配算法
  • 6.改进的模式匹配算法(KMP算法)

1.字符串定义

字符串是一种特殊的线性表,是由字符构成的有限序列,其数据元素是字符。

2.串的几个基本概念

2.1 空串:

长度为零的串称为空串,空串不包含任何字符。

2.2空格串

由一个或多个空格组成的巾。虽然空格是一个空白字符,但它也是一个字符,在计算串长度时要将其计算在内。

2.3子串

由串中任意长度的连续字符构成的序列称为子串。含有子串的串称为主串。子串在主串中的位置是指子串首次出现时,该子串的第一个字符在主串中的位置。空审是任意串的子串。

2.4串相等

指两个串长度相等且对应序号的字符也相同。

2.5串比较

两个串比较大小时以字符的ASCI码值(或其他字符编码集合作为依据实质上,比较操作从两个串的第一个字符开始进行,字符的码值大者所在的串为大,若其中一个串先结束,则以串长较大者为大。

3.串的基本操作(此处以java为例)

java中的字符串是一个final类,实现了CharSequence接口。实际内部也是也是一个字符数组,如下截图
字符串的字符数组

3.1赋值操作StrAssign(s,t)

将串s的值赋给串t。

  String s1 = new String("我是字符串1");
  String s2 = "我是字符串1";
  String s21 = "我是字符串1";
  System.out.println(s1==s2);//false
  System.out.println(s1.hashCode()==s2.hashCode()); //true
  System.out.println(s2==s21);//true
  String s3 = new String("我是字符串2");
  String s4= new String("我是字符串2");
  System.out.println(s3==s4); //false
  System.out.println(s3.hashCode()==s4.hashCode()); //true

3.2 连接操作 Concat(s,t)

将串t接续在串s的尾部,形成一个新串

String s1="我是字符串1";
String s2="我是字符串2";
System.out.println(s1.concat(s2));

3.3求串长StrLength(s)

返回串s的长度。

 String s="我是字符串";
 System.out.println(s.length());//5

3.4比较StrCompare(st)

比较两个串的大小。返回值-1、0和1分别表示st、st和s>t 三种情况。java中返回的是正值或者负值

 String s1="a";
 String s2="b";
 System.out.println(s1.compareTo(s2));//-1
 System.out.println(s2.compareTo(s1));//1

CompareTo源码

 public int compareTo(String anotherString) {
        //原始字符串的长度
        int len1 = value.length;
        //比较的字符串的长度
        int len2 = anotherString.value.length;
        //比较两个字符串相对较短的一个字符串
        int lim = Math.min(len1, len2);
        //拿到字符数组
        char v1[] = value;
        char v2[] = anotherString.value;
        //从较短的第一个字符串开始一个一个对比
        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            //字符不相等直接返回
            if (c1 != c2) {
               //两个字符的相减其实对应的acsll值相减 System.out.println('a'-'c'); -2
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

3.5 求子串_SubString(s,start,len)

返回串s中从start 开始的、长度为len 的字符序列。

 String str="helloword";
 System.out.println(str.substring(2,4));//ll
 System.out.println(str.substring(0,5));//hello

4.串的存储结构

串可以进行顺序存储或链式存储。

4.1 串的顺序存储结构

串的顺序存储结构是指用一组地址连续的存储单元来存储串值字符序列。由于串中的元素为字符,所以可通过程序语言提供的字符数组定义串的存储空间也可以根据串长的需要动态申请字符串的空间。

4.2 串的链式存储

当用链表存储串中的字符时,每个结点中可以存储一个字符,也可存储多个字符,此时要考虑存储密度问题。在链式存储结构中,结点大小的选择会直接影响串的处理效率

5.朴素的模式匹配算法

思路:从主串的第一个字符开始与模式串的第一个开始比较,相等则继续下一个字符串进行对比,相反则从主串的第二个字符开始与模式串的第一个字符串重新开始比 ,直到模式串的每一个都能与主串相等为止,则匹配成功。否则匹配失败。

此处以C语言为例子进行实现:

#include <stdio.h>
#include <string.h>
/**
 * /**
 * 比较字符串返回匹配成功的下标
 * @param s 主串
 * @param p  模式匹配串
 * @param pos 主串开始的位置
 * @return
 */
int Index(char s[],char p[],int pos) {
    //i代表匹配的位置 j代表模式串的位置,sLen代表主串的长度,pLen代表模式串的长度
    int i, j, sLen, pLen;
    //传入的主串的位置开始匹配
    i = pos;
    //模式串从第一个字符开始匹配
    j = 0;
    //计算主串和子串的长度
    sLen = strlen(s);
    pLen = strlen(p);
    while (i < sLen && j < pLen) {
        //如果两个字符匹配,则继续匹配
        if (s[i] == p[j]) {
            i++;
            j++;
        } else {
            //否则,匹配串的位置回到0位置,主串进行回到起始匹配的下一个位置进行比较
            i = i - j + 1;
            j = 0;
        }
    }
    //匹配完了,j的值一定是大于等于模式串的长度,返回的匹配开始的位置
    if (j >= pLen) {
        return i - pLen;
    }
    //匹配失败
    return -1;
}
int main() {
    char s[]="helloword";
    char p[]="word";
    int res = Index(s,p,0);
    printf( "%d",res);
    return 0;
}

结果输出

6.改进的模式匹配算法(KMP算法)

思路:
朴素的模式匹配算法存在一个问题,时间复杂度比较大,匹配的时候都是从主串的下一个位置与模式串的第一个位置开始,最坏的情况下时间复杂度为O(mxn)。

改进的模式匹配:
匹配过程中出现比较字符不相等时候,不需要退回主串的字符串位置指针,利用结构使主串尽可能滑动可能远的距离,再继续进行比较。

KMP的算法的核心是求出Next函数的过程

当模式串中的字符Pj与主串中相应的字符Si不相等时,因为前j个字符(“P0…Pj-1”)已经匹配成功,如果模式匹配中的P0…Pk-1与Pj-k…Pj-1相同,这时可以使用Pk与Si进行比较,从而使i无需回退。

令next(j)=k,表示模式串中的Pj与主串中的字符不相等时,令模式串Pnext(j)与主串的相应的字符进行比较。Next的函数表达式:

1)当j=0时,next[j]=-1
2) 当{k| 0<k<j并且P0…Pk-1=Pj-k…Pj-1},next[j]=max
3) 其他情况,next[j]=0

第二种情况比较难以理解:
目的是寻找当前j位置前的公共前后缀

/**
 * 求解模式匹配串的next数组
 * @param p  模式匹配串
 * @param next next数组
 */
void GetNext(char *p,int next[]){
    int i=0,j=-1,len;
    //模式串的长度
    len= strlen(p);
    //模式串数组的第1位肯定-1
    next[0]=-1;
    //循环求解模式串
    while(i < len){
        if(j==-1 || p[i] == p[j]){
            ++i;
            ++j;
            next[i]=j;
        }else{
            j = next[j];
        }
        printf("the %d th loop,i=%d,j=%d,next[%d]=%d",i,i,j,i,next[i]);
        printf("\n");
    }
}

测试代码:

int main() {
    char p[] = "ababa";
    int next[5] ;
    //获取next数组
    GetNext(p,next);
    for (int i = 0; i <= 5; ++i) {
        printf("%d,",next[i]);
    }
    return 0;
}

输出的结果

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

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

相关文章

j解决Ubuntu无法安装pycairo和PyGObject

环境&#xff1a;虚拟机Ubuntu20.04&#xff0c;vscode无法安装pycairo和PyGObject 虚拟机Ubuntu20.04&#xff0c;vscode中运行Anaconda搭建的vens 的Python3.8.10 首先在vscode中点击ctrlshiftp&#xff0c;选择Python3.8.10的环境&#xff0c;自动激活Python 最近在搞无人…

基于SSM的人才招聘系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

WorkPlus打造统一用户管理平台,实现企业用户管理的一体化

在企业信息化的进程中&#xff0c;统一用户管理平台扮演着重要的角色。WorkPlus作为领先的品牌&#xff0c;致力于打造一体化的统一用户管理平台&#xff0c;帮助企业实现用户管理的便捷与高效。本文将重点介绍WorkPlus如何通过创新的解决方案&#xff0c;实现企业用户管理的统…

unity fbx动画按配置切割帧片段

主要参考该文章&#xff1a;人无两度s 《unity自动切割动画》 感谢作者分享 执行代码需要将模型与配置文件(.txt)放到同一目录下&#xff0c;批量选中模型后右键&#xff0c;代码中读取了选中的第一个模型同目录下可能存在的“动画帧分段.txt”&#xff0c;按其中的配置对选中…

[HNCTF 2022 Week1]——Web方向 详细Writeup

Week1 [HNCTF 2022 Week1]2048 f12查看源代码 可以看出游戏的分数是score 修改score的值 得到flag [HNCTF 2022 Week1]Interesting_include 得到源码 <?php //WEB手要懂得搜索 //flag in ./flag.phpif(isset($_GET[filter])){$file $_GET[filter];if(!preg_match(&qu…

axios封装/基础配置

步骤&#xff1a;装包 -> 封装axios实例 ->调用实例发送请求 1. 装包 npm install axios 2. 封装 axios基础配置 // axios实例封装 import axios from axios// 创建axios实例 const axiosInstance axios.create({baseURL:http://xxx.net, //基地址timeout:5000 //…

el-table 实现表、表格行、表格列合并

最近写vue开发项目的时候&#xff0c;很多地方用到了Element组件中的Table 表格。经过一周的边学边做&#xff0c;我总结了以下三种有关表格的合并方法。 一、合并表头 话不多说&#xff0c;先看效果图 代码如下&#xff1a; 表格结构如上&#xff0c;其中:header-cell-style对…

Java进行多线程编程?(lambda表达式~)

本文标题&#xff1a;Java进行多线程编程&#xff1f;那么&#xff0c;Java为啥不学学如何进程多进程编程呢&#xff1f;&#xff1f;原因在于&#xff1a;Java圈子中不提倡多进程编程~~ 接下来&#xff0c;我们来写一个最为基础/入门的HelloWord程序来感受如何进行多线程~~ J…

数据资产管理:数据目录怎么搞?

经过了站在业务视角的自上而下的数据梳理&#xff0c;以及站在IT视角的自下而上的数据盘点&#xff0c;一套“热腾腾”的数据资产清单终于新鲜出炉了。 通过数据资产盘点&#xff0c;企业终于知道他们拥有哪些数据、如何使用数据、是否安全以及数据在哪里。 然而&#xff0c;据…

数据库误修改后的数据恢复

一不小心将数据库数据修改了&#xff0c;而且回滚无效&#xff0c;于是去尝试各种方法恢复数据 查询到修改时间点之前的数据 恢复数据 恢复数据库被修改数据的流程及代码&#xff0c;这里被修改的表是AUTH_USER,实际应用填写对应表名。 -- 通过时间恢复删除且已提交的数据-- 1…

Jenkins安装配置及插件安装使用

个人理解持续集成&#xff1a;为解决程序代码提交质量低,提交内容导致原有系统的BUG&#xff0c;按时或按需自动编译版本&#xff0c;进行自动化测试。 百度对持续集成的定义&#xff1a;持续集成是一种软件开发实践&#xff0c;即团队开发成员经常集成他们的工作&#xff0c;…

配额 安排

一 常用Tcode 基于Tcode的顺序排列 供应商主数据物料主数据货源清单配额安排采购信息记录采购订单框架协议采购询价/报价采购申请订单收货发票校验物料需求计划BP-供应商主数据MM01 - 物料主数据新增ME01 - 维护MEQ1 - 维护ME11 - 创建ME21N - 创建框架协议-合同&#xff1a…

Qt6_贪吃蛇Greedy Snake

贪吃蛇Greedy Snake 1分析 首先这是一个贪吃蛇界面&#xff0c;由一个长方形边框和一只贪吃蛇组成 默认开局时&#xff0c;贪吃蛇身体只有3个小方块&#xff0c;使用画笔画出 1.1如何移动 对于蛇的移动&#xff0c;有2种方法 在一定时间范围内(定时器)&#xff0c;未对游戏…

谷歌 reCAPTCHA 人机验证

一、问题 smogon 论坛注册不成功。输入账号、密码、邮箱后显示 You did not complete the CAPTCHA verification properly. Please try again. 即未通过 CAPTCHA 验证。 二、原因 使用的 CAPTCHA 验证是谷歌的 reCAPTCHA 人机验证&#xff0c;国内无法访问谷歌服务。 三、解决…

分页查询实现

目录 1.实体类 2.Mapper层 2.1.xxxMapper接口 2.2.xxxMapper.xml文件 3.Service层 3.1.xxxService接口 3.2.xxxServiceImpl层 4.xxxController层 5.调用接口 6.总结 1.实体类 与数据库交互和与前端交互的实体类 这个Model是与数据库交互的实体类&#xff0c;其中的…

python调用GPT实现:智能用例生成工具

工具作用&#xff1a; 根据输入的功能点&#xff0c;生成通用测试点 实现步骤 工具实现主要分2个步骤&#xff1a; 1.https请求调用Gpt,将返回响应结果保存为.md文件 2.用python实现 将 .md文件转换成.xmind文件 3.写个简单的前端页面&#xff0c;调用上述步骤接口 详细代…

7个数据科学Python库将为您节省大量时间

7个数据科学Python库将为您节省大量时间 在进行数据科学时&#xff0c;您可能会花费大量时间编写代码并等待计算机运行某些操作。我挑选了一些可以在这两种情况下节省您时间的Python库。即使您只将其中一个库纳入您的工具库&#xff0c;您仍然可以在下次项目工作时节省宝贵的时…

揭示OLED透明屏数据:探索未来显示技术的潜力

OLED透明屏作为一项颇具吸引力的显示技术&#xff0c;以其独特的特点和卓越的画质在市场上引起了广泛关注。 在这篇文章中&#xff0c;尼伽将和大家一起深入探索OLED透明屏的数据&#xff0c;通过具体的市场趋势分析、技术指标解析、应用领域探讨和未来前景展望&#xff0c;为…

【C++基础】实现日期类

​&#x1f47b;内容专栏&#xff1a; C/C编程 &#x1f428;本文概括&#xff1a; C实现日期类。 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&#xff1a;2023.9.7 对于类的成员函数的声明和定义&#xff0c;我们在类和对象上讲到过&#xff0c;需要进行…

mac 查看端口占用

sudo lsof -i tcp:port # 示例 sudo lsof -i tcp:8080 杀死进程 sudo kill -9 PID # 示例 sudo kill -9 8080