当前位置: 首页 > web >正文

数据结构之串

一、串的定义与基本概念

1. 串的定义

定义:串是由零个或多个字符组成的有限序列,记作 s="a1​a2​…an​",例如 "data structure"、"123" 等。

  • 空串:无任何字符,长度为 0,用 "" 表示,例如短信内容为空时即为空串。
  • 空格串:由一个或多个空格组成,有长度,例如 " "(3 个空格)。
  • 子串与主串:子串是主串中连续字符序列。
    • 生活实例:回文诗 “上海自来水来自海上” 是一个串,其正读和反读相同,体现了串的逆序特性;英文单词 “friend” 中,“end” 是子串,“friend” 是主串。

2. 串的比较

规则:基于字符的 ASCII/Unicode 编码逐个比较,直到找到首个不同字符或遍历完较短串。

  • 例 1:"apple" vs "apricot",前两个字符 “ap” 相同,第三个字符 “p”(ASCII 112)<“r”(ASCII 114),故 "apple" < "apricot"。
  • 例 2:"abc" vs "ab",前两个字符相同,短串先遍历完,故 "abc" > "ab"。

二、串的抽象数据类型(ADT)

基本操作

  • 赋值:将一个串的内容复制到另一个串。

  • 比较:逐个字符按ASCII码值比较,决定串的大小关系。

  • 连接:将两个串首尾相连,形成新串。

  • 求子串:从主串的指定位置截取固定长度的子串。

  • 替换:将主串中某子串替换为另一个串。

  • 插入:在指定位置插入子串。

  • 删除:删除主串中指定位置的子串。

生活实例:微信聊天时,发送前编辑文字(赋值)、转发消息(复制)、撤回消息(清空),以及搜索聊天记录中的关键词(定位),都是串操作的典型应用。

三、串的存储结构

1. 顺序存储

  • 用数组存储,如 C 语言中用 char str[100] 存储字符串。
  • 优缺点
    • 优点:随机访问快(如取第 5 个字符直接通过下标)。
    • 缺点:插入 / 删除需移动元素,可能溢出。
  • 生活实例:手机短信长度限制(如 70 字),若输入超过,需截断或分段,类似顺序存储的固定容量限制。

2. 链式存储

  • 用链表结点存储字符,每个结点可存多个字符以减少空间浪费。
  • 优点:动态灵活,插入 / 删除方便(如聊天记录不断新增,无需预先分配固定长度)。
  • 缺点:随机访问慢,需遍历。

四、模式匹配算法

1. 朴素模式匹配算法

  • 思路:从主串每个位置开始,逐个字符匹配子串,最坏时间复杂度 O((n−m+1)×m)。
  • 生活实例:在一本小说中查找 “英雄” 一词,每次从当前位置开始逐字对比,若每次都在子串末尾发现不匹配(如主串是 “英雄气短”,子串是 “英雄豪杰”),需多次回溯,效率低。

2. KMP 算法

  • 核心思想:利用部分匹配信息避免不必要的回溯。

  • 部分匹配表(Next数组)

    • 定义:next[j] 表示模式串前 𝑗j 个字符的最长公共前后缀长度。

    • 计算示例(模式串 "ABCDABD"):

      j0123456
      模式串ABCDABD
      next[j]-1000012
    • 匹配过程:当字符失配时,模式串右移 𝑗−𝑛𝑒𝑥𝑡[𝑗]j−next[j] 位。

  • 时间复杂度:𝑂(𝑛+𝑚)O(n+m),显著优于朴素算法。

六、KMP算法的实现细节

  1. Next数组的推导

    • 初始化 next[0] = -1

    • 通过递推计算每个位置的 next[j],利用已计算的 next 值减少重复比较。

  2. 优化Next数组

    • 若 pattern[j] == pattern[next[j]],则 nextval[j] = nextval[next[j]],进一步减少比较次数。

    • 代码示例:

#include <iostream>
#include <string>
#include <vector>// 朴素模式匹配算法
int naivePatternMatching(const std::string& text, const std::string& pattern) {int n = text.length();int m = pattern.length();for (int i = 0; i <= n - m; ++i) {int j;for (j = 0; j < m; ++j) {if (text[i + j] != pattern[j]) {break;}}if (j == m) {return i;}}return -1;
}// 计算next数组
void computeNext(const std::string& pattern, std::vector<int>& next) {int m = pattern.length();int len = 0;next[0] = 0;int i = 1;while (i < m) {if (pattern[i] == pattern[len]) {len++;next[i] = len;i++;}else {if (len != 0) {len = next[len - 1];}else {next[i] = 0;i++;}}}
}// KMP算法
int kmpPatternMatching(const std::string& text, const std::string& pattern) {int n = text.length();int m = pattern.length();std::vector<int> next(m);computeNext(pattern, next);int i = 0;int j = 0;while (i < n) {if (pattern[j] == text[i]) {j++;i++;}if (j == m) {return i - j;}else if (i < n && pattern[j] != text[i]) {if (j != 0) {j = next[j - 1];}else {i = i + 1;}}}return -1;
}int main() {std::string text = "ABABDABACDABABCABAB";std::string pattern = "ABABCABAB";// 朴素模式匹配int naiveIndex = naivePatternMatching(text, pattern);if (naiveIndex != -1) {std::cout << "朴素模式匹配: 模式串在主串中的位置是 " << naiveIndex << std::endl;}else {std::cout << "朴素模式匹配: 未找到模式串" << std::endl;}// KMP模式匹配int kmpIndex = kmpPatternMatching(text, pattern);if (kmpIndex != -1) {std::cout << "KMP模式匹配: 模式串在主串中的位置是 " << kmpIndex << std::endl;}else {std::cout << "KMP模式匹配: 未找到模式串" << std::endl;}return 0;
}

http://www.xdnf.cn/news/4642.html

相关文章:

  • 【PmHub后端篇】PmHub Gateway全局过滤器:接口调用耗时统计及黑白名单配置技术深度解析
  • 57.[前端开发-前端工程化]Day04-webpack插件模式-搭建本地服务器
  • XML语言
  • 企业开发平台大变革:AI 代理 + 平台工程重构数字化转型路径
  • Android单例模式知识总结
  • 02_JVM
  • Mockoon 使用教程
  • 为什么使用Less替代原始CSS?
  • 学习黑客MAC 地址
  • 数字孪生市场格局生变:中国2025年规模214亿,工业制造领域占比超40%
  • 安卓应用卡顿、性能低下的背后原因
  • 【文献阅读】Depth Anything Unleashing the Power of Large-Scale Unlabeled Data
  • 2025-05-08 Unity 网络基础9——FTP通信
  • Linux的基础开发工具
  • 手机上使用的记录笔记的软件推荐哪一款
  • SAP 交货单行项目含税金额计算报cx_sy_zerodivide处理
  • 云手机虚拟地址技术的运营场景
  • n8n - 开放灵活的智能自动化工作流平台
  • uniapp自定义步骤条(可二开进行调试)
  • shader中性能优化
  • docker 部署clickhouse
  • App Store支付新政重构跨境电商生态:eBay卖家的突围之道
  • vue中scss使用js的变量
  • OpenCv实战笔记(3)基于opencv实现调用摄像头并实时显示画面
  • 【WEB3】区块链、隐私计算、AI和Web3.0——隐私计算(2)
  • 【计算机网络】Cookie、Session、Token之间有什么区别?
  • Angular 面试常见问题
  • maven如何搭建自己的私服(windows版)?
  • 住宅 IP 地址:数字时代的真实网络身份载体
  • Git 基础操作系列2: 本地项目上传至git仓库(gitee / gitlab / github)