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

Avalonia UI的演进逻辑与Qt生态深度对比

堪粤尚冀最长相等真前后缀

最长相等前后缀也被称为 Border ,KMP算法就利用了其性质来进行匹配优化。

前缀:从字符串第一个字符开始的子串。

后缀:以字符串最后一个字符结束的子串。

真:长度严格小于原字符串长度。

求法(

?

(

?

2

)

O(n

2

) ):

def border(s):

n = len(s)

L = 0

for i in range(1, n): # 长度为 i 上限为 n-1 确保为真前后缀

if s[:i] == s[n-i:n]:

L = i

return L

还有更加高效的算法,可以优化到

?

(

?

)

O(n) 。正是这个优化产生了 KMP 算法。

前缀函数

在 KMP 中的前缀函数的到数组

?

π ,其中

?

[

?

]

π[i] 表示字符串的前缀

?

[

0

?

]

t[0…i] 中,最长的相等真前后缀的长度。

如果使用暴力枚举每个子串进行一次 border 函数的话时间复杂度是

?

(

?

3

)

O(n

3

)

b = []

for i in range(len(s)):

b.append(border(s[:i + 1]))

通过递推可以在

?

(

?

)

O(n) 时间内求出前缀数组

?

π

假设我们正在计算

?

[

?

]

π[i] ,并且已知

?

[

?

?

1

]

=

?

π[i?1]=j 。

这意味着

?

[

0

?

?

1

]

t[0…j?1] 是

?

[

0

?

?

1

]

t[0…i?1] 的最长相等前后缀。

情况A:如果

?

[

?

]

=

=

?

[

?

]

t[i]==t[j] ,那么

?

[

?

]

=

?

+

1

π[i]=j+1 。

情况B:如果

?

[

?

]

?

[

?

]

t[i]

=t[j] ,我们需要一个更短的相等前后缀。于是我们可以让

?

=

?

[

?

?

1

]

j=π[j?1] ,然后重复

?

[

?

]

t[i] 和

?

[

?

]

t[j] 的比较过程,直到匹配或

?

j 降为

0

0 。

具体代码为

def get_pi(s):

n = len(s)

pi = [0] * n

for i in range(1, n):

j = pi[i - 1] # 取前一个的位置的pi

while j > 0 and s[i] != s[j]: # 情况B

j = pi[j - 1]

if s[i] == s[j]: # 情况A

j += 1

pi[i] = j

return pi

应用

模式串匹配

已知模式串

?

t 和匹配串

?

s ,在预处理完模式串的

?

π 数组后可以通过双指针匹配。

指针

?

i :始终在

?

s 上向右移动,不回退。

指针

?

j :在

?

t 上移动,如果匹配 j++ 如果失配

?

j 根据

?

π 数组向左跳,跳到一个可以让前面部分继续匹配的位置。

这个根据

?

π 数组向左跳的过程可以理解成下面这句有名名的话:

一个人能走的多远不在于他在顺境时能走的多快,而在于他在逆境时多久能找到曾经的自己。

m, n = len(t), len(s)

pi = get_pi(t)

j = 0 # 模式串指针

for i in range(n): # 文本串指针永不回退

while j > 0 and s[i] != t[j]:

j = pi[j - 1]

if s[i] == t[j]:

j += 1

if j == m: # 匹配成功

# 位置为 i - j + 1 0-based

j = pi[j - 1] # 继续匹配可能重叠的下一处

求字符串周期

先利用预处理的

?

π 数组求出所有的 Border ,再根据这些 Border 就可以构造出所有的周期串了。

求字符串所有周期

由于

?

π 数组记录了最长 Border ,而次长的 Border 可能通过

?

[

?

[

?

?

1

]

?

1

]

π[π[n?1]?1] 递归求得,因此我们可以不断回跳,求出所有的 Border 后,周期就是 n - Border。

n = len(s)

pi = get_pi(s)

b = []

k = pi[n - 1]

while k:

b.append(n - k)

k = pi[k - 1]

b.append(n)

print(*b)

不要忘记了

?

s 自身也是周期,然后每个周期串就是 s[:b[i]] 。

完全循环

?

[

?

?

1

]

>

0

π[n?1]>0 基础上,当它的最小正周期

?

?

?

[

?

?

1

]

n?π[n?1] 可以被总长度

?

n 整除时,存在完全循环。

n = len(s)

pi = get_pi(s)

k = n - pi[n - 1]

print("YES" if pi[n - 1] > 0 and n % k == 0 else "NO")

http://www.cnnetsun.cn/news/1503486.html

相关文章:

  • 如何快速掌握ComfyUI BiRefNet背景移除:从新手到专家的完整教程
  • Java面试突击版!快速拿下offer的神技!面试题分享!
  • Go Mutex 与 RWMutex 性能对比
  • PFC(6.0)基于GBM模型的矿物晶体岩石单轴压缩模拟与裂纹监测分析
  • hongzh0Xstream历史漏洞审计
  • 域环境基础知识
  • MySQL技巧(八) :死锁解决与实战案例
  • 基于单片机的汽车智能胎压监测预警系统设计
  • 还在到处找免费云服务器?2026年最新白嫖攻略,亲测可用!
  • GetQzonehistory完整教程:如何轻松备份QQ空间历史说说的终极指南
  • Python爬虫避坑指南:用httpx和Crypto库破解有道翻译API的常见问题与解决方案
  • 【机械臂路径规划】基于RRT星算法规划 Lynx 机械臂从起始位姿到目标位姿的最短无碰撞路径附matlab代码
  • 3步攻克科研数据提取难关:WebPlotDigitizer开源工具实战指南
  • 别再混淆了!5分钟搞懂光学设计中的‘快轴’、‘慢轴’与波片选型核心参数
  • 别再被路径搞晕了!详解YOLOv8中settings.yaml与data.yaml的‘双YAML’配置哲学
  • ROS Noetic + RealSense D435i:从驱动安装到RVIZ点云显示的完整工作流解析
  • 嵌入式天文时间服务库:日出日落计算与事件调度
  • Modbus通信协议详解:原理、实现与应用
  • Vivado仿真避坑指南:从D触发器到RAM/ROM,新手最容易搞错的时序逻辑仿真细节
  • MayeNano
  • 紧迫感陷阱:时间压力作为网络钓鱼攻击核心向量的机制分析与防御策略
  • FreeCAD 1.1 (Linux, macOS, Windows) - 开源的参数化 3D 建模软件
  • AutoSAR实战:NVRAM Manager配置避坑指南(附完整代码示例)
  • PyTorch随机矩阵生成全攻略:从基础rand到高级randperm的实战解析
  • 保姆级教程:如何快速将nvm的npm源从淘宝镜像切换到npmmirror.com
  • 摆脱论文困扰!高效论文写作全流程AI论文写作软件推荐(2026 最新)
  • 第一批“首席龙虾官”,月薪6万
  • TongHttpServer不只是负载均衡:一次搞懂主程序、HA与控制台的配置与联动
  • 嵌入式硬件工程师职业发展路径与技术方向
  • 魔兽地图格式转换终极指南:w3x2lni如何让地图开发效率提升300%