字符串科技

你说的对,但字符串或串(String)是由数字、字母、下划线组成的一串字符。一般记为 s="a1a2···an"(n>=0)。它是编程语言中表示文本的数据类型。在程序设计中,字符串(string)为符号或数值的一个连续序列,如符号串(一串字符)或二进制数字串(一串二进制数字)。

字符串匹配

你说的对,但字符串匹配是计算机科学中最古老、研究最广泛的问题之一。一个字符串是一个定义在有限字母表∑上的字符序列。例如,ATCTAGAGA是字母表∑ = {A,C,G,T}上的一个字符串。字符串匹配问题就是在一个大的字符串T中搜索某个字符串P的所有出现位置。其中,T称为文本,P称为模式,T和P都定义在同一个字母表∑上。

一些定义:

字符串匹配:又称模式匹配(pattern matching)。该问题可以概括为「给定字符串 ST,在主串 S 中寻找子串 T」。字符 T 称为 模式串 (pattern)。

暴力做法:从主串 S 的每个位置开始与模式串 T 向后匹配,若匹配不成功,则从主串下一个位置与模式串重新匹配。

时间复杂度:O(nm)

实际上暴力算法在随机数据下表现良好——匹配成功的字符数量越多,匹配的概率越低。

但卡到 O(nm) 也很容易(

KMP 算法

主要思想:充分利用匹配失败的信息,跳过某些已经判断为匹配失败的位置。

如果字符串 s 的长度为 d 的前缀 (1d<|s|) 和长度为 d 的后缀相等,称这个前缀是 s 的一个 border ,将前缀 s[1i] 的最长 border 长度记作 next(i)

border 的性质:s[1i] 的所有 border 长度分别为 next(i),next(next(i)),next(next(next(i)))...

如果当前已经成功匹配了 i 个字符,且第 i+1 个字符不匹配,那么根据 next(i) 的定义,主串 S 中从后往前数 next(i) 位也一定都与模式串 T1next(i) 位匹配。

于是将 T 上匹配指针从 i 转到 next(i),再与 S 的字符匹配。

有点抽象,举个栗子:

S ABABABC
T ABABC

算出 next(i)

next 0 0 1 2 0

第一次匹配失败:

S ABAB.ABC
T ABAB.C
next 0 0 1 2 0

T 上匹配指针从 4 转到 next(4),继续匹配:

S ABABABC
T   ABABC
next 0 0 1 2 0

匹配成功。

这样做是 O(n) 的,因为 j 只能在匹配成功时增加 1,最多增加 n 次,从而最多减少 n 次,也就是嵌套 next(i) 最多 n 次。

于是问题就在于如何快速求出 next(i)

暴力求显然不现实,考虑线性递推。

已知 next(1)next(i),考虑如何计算出 next(i+1)

j=next(i)+1

如果 s[j]s[i+1] 不相等,就让 next(j)j,直至 s[j]s[i+1] 相等,此时 next(i+1)=next(j)+1

发现计算 next(i) 的过程实际上就是 S 与本身匹配。

posted @   象征阳光  阅读(8)  评论(0编辑  收藏  举报  
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示