高效求解“不含禁用词的最长子串”问题:O(mn) 双指针优化方案

花韻仙語

花韻仙語

2026-08-01

999人浏览

原创

高效求解“不含禁用词的最长子串”问题:O(mn) 双指针优化方案

给定一个字符串和最多10个禁用词,需找出不包含任一禁用词作为子串的最长连续子串长度;本文介绍基于双指针与后缀匹配优化的 o(mn) 解法,避免暴力截取与 contains 导致的 o(mn²) 开销。

给定一个字符串和最多10个禁用词,需找出不包含任一禁用词作为子串的最长连续子串长度;本文介绍基于双指针与后缀匹配优化的 o(mn) 解法,避免暴力截取与 contains 导致的 o(mn²) 开销。

在字符串处理类问题中,“最长合法子串”常可通过滑动窗口(双指针)解决,但关键在于如何高效判断窗口内是否新增了非法模式。原代码使用 substring() + contains() 的组合,每次迭代都重建子串并遍历所有禁用词进行子串搜索,导致最坏时间复杂度高达 O(m·n²)(其中 n 为字符串长度,m 为禁用词数量),无法应对 10⁵ 规模输入。

核心优化思路是:不检查整个子串是否含禁用词,而只检查以右端点 i 结尾的新后缀是否恰好匹配某个禁用词。因为当左指针 j 固定时,仅当新加入字符 s[i] 使 s[j..i] 首次出现禁用词时,该禁用词必然以位置 i 结尾。因此,我们只需验证所有禁用词是否为 s[?..i] 的后缀——即检查 s[i−len+1..i] 是否等于某禁用词。

由此可设计 O(mn) 算法:

ColorMagic
ColorMagic

AI调色板生成工具

下载
  • 维护滑动窗口 [j, i](左闭右闭,长度为 i−j+1);
  • 对每个 i,从 j 开始向右收缩(j++),直到 s[j..i] 不以任何禁用词结尾;
  • 每次收缩仅需检查至多 m 个禁用词,且每个禁用词比较最多 10 次(因词长 ≤10),故单次 endsWith 为 O(m);
  • 关键性质:i 和 j 各自最多递增 n 次,总操作数 ≤ 2n,因此整体时间复杂度为 O(mn),空间复杂度 O(1)。

以下是完整、可运行的 Java 实现:

public int solve(String s, List<string> words) {
    if (s == null || s.isEmpty()) return 0;
    int n = s.length(), j = 0, ans = 0;

    for (int i = 0; i  words) {
    for (String word : words) {
        if (endsWith(s, begin, end, word)) {
            return true;
        }
    }
    return false;
}

// 判断 s[begin..end] 是否以 word 结尾
private boolean endsWith(String s, int begin, int end, String word) {
    int len = word.length();
    int startIdx = end - len + 1; // word 在 s 中应起始的位置
    if (startIdx <p>⚠️ 注意事项:</p>
<ul>
<li>禁用词长度上限为 10,因此 endsWith 内部循环为常数级,这是 O(mn) 成立的前提;</li>
<li>原题示例 s = "helloworld", words = ["wor", "rld"]:当 i=6(对应 'o',索引从0开始),s[0..6]="hellowo",检查后缀 "owo"、"lowo" 等均不匹配;而 i=7 时 s[0..7]="hellowor",后缀 "wor" 匹配,触发 j++,最终最大合法长度为 7;</li>
<li>若需返回具体子串而非长度,可在更新 ans 时同步记录 bestJ 和 bestI;</li>
<li>本解法未使用 Trie 或 KMP,因其在 m ≤ 10 且 word.length ≤ 10 场景下无必要开销;若 m 显著增大(如 ≥1000),则建议构建 Aho-Corasick 自动机实现 O(n)。</li>
</ul>
<p>总结:通过将“全局子串检测”降维为“右对齐后缀匹配”,结合双指针的单调性保证,我们成功将时间复杂度从不可接受的 O(mn²) 优化至线性级别 O(mn),兼顾简洁性与工程实用性。</p></string>

相关专题

更多
C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

114

31

墨刀AI提示词教学
墨刀AI提示词教学

本合集由PHP中文网精心整理,为您提供全面的墨刀AI提示词教学。内容涵盖高质量原型撰写公式与实操窍门,助您轻松掌握AI设计工具。无论是零基础入门还是进阶技巧,都能让您快速上手,大幅提升产品设计与协作效率。

2026.08.04

6

21

墨刀AI完整入门
墨刀AI完整入门

PHP中文网为您倾力打造墨刀AI保姆级入门指南完整版!本合集从零基础讲起,涵盖AI生成原型、提示词优化、图片转原型及多轮对话等核心功能。无论您是新手还是进阶用户,都能轻松掌握产品设计全流程。快来PHP中文网,一键解锁高效设计技巧,让想法即刻成型!

2026.08.04

1

20

墨刀AI进阶技巧
墨刀AI进阶技巧

本合集由PHP中文网精心整理,为您提供墨刀AI核心进阶策略指南。内容涵盖高效提示词写作、原型智能生成与微调、结构化导图制作及行业分析报告输出等实战技巧。助您轻松掌握AI设计工具,大幅提升产品设计与团队协作效率。

2026.08.04

6

14

火山引擎实名认证失败怎么办
火山引擎实名认证失败怎么办

火山引擎实名认证失败可能与证件信息填写错误、姓名或企业信息不一致、证件照片不清晰、营业执照状态异常、手机号验证失败或审核资料不完整有关。本专题整理个人认证、企业认证、资料上传、审核退回、重新提交和认证不通过的常见处理方法。

2026.08.04

4

10

火山引擎域名备案流程详解
火山引擎域名备案流程详解

火山引擎域名备案适合需要在火山引擎云服务器、对象存储、CDN或网站服务上绑定域名的用户参考。本专题整理备案入口、账号实名认证、备案类型选择、主体信息填写、网站信息提交、资料上传、初审核验、管局审核和备案失败排查,帮助用户完成网站上线前的备案流程。

2026.08.04

0

10

火山引擎DNS解析配置步骤
火山引擎DNS解析配置步骤

使用火山引擎DNS解析网站域名时,需要确认域名已完成管理接入,并正确配置服务器IP、CNAME地址或验证记录。本专题整理域名添加、记录类型选择、TTL设置、解析状态检查、备案和访问测试等流程,适合新手搭建网站时参考。

2026.08.04

0

10

火山引擎对象存储使用教程
火山引擎对象存储使用教程

火山引擎对象存储适合用于网站图片、视频文件、备份数据、静态资源和应用附件管理。本专题整理TOS控制台入口、存储桶创建、地域选择、权限设置、文件上传、访问链接生成、CDN加速、费用查看和常见上传或访问失败问题,帮助用户快速掌握对象存储基础操作。

2026.08.04

1

10

火山引擎云服务器使用教程
火山引擎云服务器使用教程

火山引擎云服务器使用教程适合第一次购买、部署和管理云服务器的用户参考。本专题整理控制台入口、实例创建、地域和配置选择、系统镜像设置、安全组放行、远程连接、网站部署、续费计费和常见连接失败问题,帮助用户快速完成云服务器基础使用流程。

2026.08.04

3

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
JavaScript正则表达式基础与实战
JavaScript正则表达式基础与实战

共11课时 | 1.6万人学习

布尔教育正则表达式视频教程
布尔教育正则表达式视频教程

共14课时 | 4.9万人学习