You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C语言高效计算字符串前缀与另一字符串的相似度得分?

字符串前缀相似度得分计算的高效解法

问题1:是否存在O(|S| + |C|)复杂度的算法组合?

是的,完全可以通过KMP失败数组+后缀自动机/AC自动机的组合,在O(|S| + |C|)时间内完成H(命中次数)和L(抄袭可能性)的计算:

  • L值计算:基于KMP失败数组,用动态规划线性处理所有C的前缀,时间复杂度O(|C|)。
  • H值计算:有两种高效方案可选:
    • 后缀自动机方案:先将S构建为后缀自动机(O(|S|)时间),再遍历C的每个前缀,在自动机中查询其在S中的出现次数(总时间O(|C|))。
    • AC自动机方案:将C的所有前缀作为模式串构建AC自动机(本质是对C构建字典树+失败指针,O(|C|)时间),然后遍历S一次统计各前缀的出现次数(O(|S|)时间)。

两种方案均能严格满足O(|S| + |C|)的时间要求,适配长度达5×10^6的字符串。

问题2:如何用动态规划高效计算每个前缀的L值?

L值的计算核心是利用KMP的失败数组(fail数组),结合动态规划避免重复计算,步骤如下:

1. 构建C的失败数组

对字符串C计算KMP的fail数组,其中fail[i]表示C的前i个字符组成的前缀中,既是前缀又是后缀的最长子串的长度(索引从1开始,对应前缀长度i)。

2. 动态规划递推L值

定义dp[i]为C的前i个字符前缀的L值:

  • 初始条件:dp[1] = 1(长度为1的前缀只有自身满足条件)。
  • 递推公式:对于i>1,dp[i] = dp[fail[i]] + 1(约定dp[0] = 0)。

原理:fail[i]对应的前缀是当前前缀最长的“前后公共前缀”,所有满足条件的子串包含该最长前缀的全部满足条件子串,再加上当前前缀自身,因此只需在dp[fail[i]]的基础上加1即可。

这种递推是线性的,每个dp[i]仅依赖dp[fail[i]],时间复杂度O(|C|),完全符合递增计算的要求。

例如,对于C="ababab",其fail数组为[0,0,1,2,3,4](索引1-6),对应的dp数组为:

  • dp[1] = 1
  • dp[2] = dp[0] + 1 = 1
  • dp[3] = dp[1] + 1 = 2
  • dp[4] = dp[2] + 1 = 2
  • dp[5] = dp[3] + 1 = 3
  • dp[6] = dp[4] + 1 = 3

这与实际结果一致:"ababab"的满足条件前缀有长度6、4、2,共3个,L值为3。

内容的提问来源于stack exchange,提问作者NatsumiStar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:05:15