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

【滑动窗口】串联所有单词的⼦串(hard)

串联所有单词的⼦串(hard)

  • 题⽬描述:
  • 解法⼀(暴⼒解法):
    • 算法思路:
    • C++ 算法代码:
    • Java 算法代码:

题⽬链接:30. 串联所有单词的⼦串

题⽬描述:

给定⼀个字符串 s 和⼀个字符串数组 words。 words 中所有字符串 ⻓度相同。
s 中的 串联⼦串 是指⼀个包含 words 中所有字符串以任意顺序排列连接起来的⼦串。
◦ 例如,如果 words = [“ab”,“cd”,“ef”], 那么"abcdef",“abefcd”,“cdabef”,“cdefab”,“efabcd”, 和 “efcdab” 都是串联⼦串。 “acdbef” 不是串联⼦串,因为他不是任何 words 排列的连接。
返回所有串联字串在 s 中的开始索引。你可以以 任意顺序 返回答案。
⽰例 1
输⼊:s = “barfoothefoobarman”, words = [“foo”,“bar”]
输出:[0,9]
解释:因为 words.length = = 2 同时 words[i].length = = 3,连接的⼦字符串的⻓度必须为 6。
⼦串 “barfoo” 开始位置是 0。它是 words 中以 [“bar”,“foo”] 顺序排列的连接。
⼦串 “foobar” 开始位置是 9。它是 words 中以 [“foo”,“bar”] 顺序排列的连接。
输出顺序⽆关紧要。返回 [9,0] 也是可以的。
⽰例 2
输⼊:s = “wordgoodgoodgoodbestword”, words = [“word”,“good”,“best”,“word”]
输出:[]
解释:因为 words.length = = 4 并且 words[i].length = = 4,所以串联⼦串的⻓度必须为 16。
s 中没有⼦串⻓度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回⼀个空数组。
⽰例 3:
输⼊:s = “barfoofoobarthefoobarman”, words = [“bar”,“foo”,“the”]
输出:[6,9,12]
解释:因为 words.length = = 3 并且 words[i].length = = 3,所以串联⼦串的⻓度必须为 9。
⼦串 “foobarthe” 开始位置是 6。它是 words 中以 [“foo”,“bar”,“the”] 顺序排列的连接。
⼦串 “barthefoo” 开始位置是 9。它是 words 中以 [“bar”,“the”,“foo”] 顺序排列的连接。
⼦串 “thefoobar” 开始位置是 12。它是 words 中以 [“the”,“foo”,“bar”] 顺序排列的连接。
提⽰
1 <= s.length <= 104
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i] 和 s 由⼩写英⽂字⺟组成

解法⼀(暴⼒解法):

算法思路:

如果我们把每⼀个单词看成⼀个⼀个字⺟,问题就变成了找到「字符串中所有的字⺟异位词」。⽆⾮就是之前处理的对象是⼀个⼀个的字符,我们这⾥处理的对象是⼀个⼀个的单词。

C++ 算法代码:

class Solution{
public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> ret;unordered_map<string, int> hash1; // 保存 words ⾥⾯所有单词的频次for(auto& s : words) hash1[s]++;int len = words[0].size(), m = words.size();for(int i = 0; i < len; i++) { // 执⾏ len 次unordered_map<string, int> hash2; // 维护窗⼝内单词的频次for(int left = i, right = i, count = 0; right + len <= s.size(); right += len){// 进窗⼝ + 维护 countstring in = s.substr(right, len);hash2[in]++;if(hash1.count(in) && hash2[in] <= hash1[in]) count++;// 判断if(right - left + 1 > len * m){// 出窗⼝ + 维护 countstring out = s.substr(left, len);if(hash1.count(out) && hash2[out] <= hash1[out]) count--;hash2[out]--;left += len;}// 更新结果if(count == m) ret.push_back(left);}}return ret;}
}

Java 算法代码:

class Solution{public List<Integer> findSubstring(String s, String[] words){List<Integer> ret = new ArrayList<Integer>();// 保存字典中所有单词的频次Map<String, Integer> hash1 = new HashMap<String, Integer>(); for(String str : words) hash1.put(str, hash1.getOrDefault(str, 0) + 1);int len = words[0].length(), m = words.length;for(int i = 0; i < len; i++) { // 执⾏次数// 保存窗⼝内所有单词的频次Map<String, Integer> hash2 = new HashMap<String, Integer>(); for(int left = i, right = i, count = 0; right + len <= s.length(); right += len){// 进窗⼝ + 维护 countString in = s.substring(right, right + len);hash2.put(in, hash2.getOrDefault(in, 0) + 1);if(hash2.get(in) <= hash1.getOrDefault(in, 0)) count++; // 判断if(right - left + 1 > len * m){// 出窗⼝ + 维护 countString out = s.substring(left, left + len);if(hash2.get(out) <= hash1.getOrDefault(out, 0)) count--;hash2.put(out, hash2.get(out) - 1);left += len;}// 更新结果if(count == m) ret.add(left);}}return ret;}
}
http://www.xdnf.cn/news/611.html

相关文章:

  • 常用的几种 Vue 父子组件传值方式
  • redis+lua脚本
  • 【英语语法】词法---动词
  • hadoop分布式部署
  • Linux `init 5` 相关命令的完整使用指南
  • Android学习总结之APK打包流程
  • 【踩坑记录】Pico串流SteamVR绿屏解决方案:排查兼容性问题与Windows系统升级指南
  • STM32 HAL库FreeRTOS 中断管理
  • XSS学习1之http回顾
  • 【读书笔记·VLSI电路设计方法解密】问题63:为什么可测试性设计对产品的财务成功至关重要
  • 机器学习周报-文献阅读
  • FastAPI-MCP
  • 8节串联锂离子电池组可重构buck-boost均衡拓扑结构 simulink模型仿真
  • 个人所得税
  • DeepSeek R1 7b,Langchain 实现 RAG 知识库 | LLMs
  • 抽象工厂模式及其在自动驾驶中的应用举例(c++代码实现)
  • 秒杀抢购系统架构与优化全解:从业务特性到技术落地
  • tigase源码学习杂记-组件化设计
  • AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年4月20日第58弹
  • 智能体团队 (Agent Team)
  • 考研系列-计算机网络-第三章、数据链路层
  • Linux:网络基础
  • 深入理解 Transformer:原理、架构与注意力机制全景图解
  • 微信怎么绑定孩子的医保卡
  • w299基于Java的家政服务平台设计与实现
  • idea中运行groovy程序报错
  • FISCO 2.0 安装部署WeBASE与区块链浏览器(环境搭建)
  • 【Linux学习笔记】Linux的环境变量和命令行参数
  • 【支付】支付宝支付
  • FastAPI:现代高性能Python Web框架的技术解析与实践指南