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

28. 找出字符串中第一个匹配项的下标

题目

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

示例 1:
输入:haystack = “sadbutsad”, needle = “sad”
输出:0
解释:“sad” 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

示例 2:
输入:haystack = “leetcode”, needle = “leeto”
输出:-1
解释:“leeto” 没有在 “leetcode” 中出现,所以返回 -1 。

提示:

  • 1 <= haystack.length, needle.length <= 104
  • haystack 和 needle 仅由小写英文字符组成

解题思路

暴力解法

  • 处理边界条件:len_h 和 len_n比较
  • 遍历数组haystack,一旦其中有字符和needle首字符相匹配,进入匹配判断
  • 判断匹配直接返回下标,若不匹配继续遍历数组haystack,直到结束

暴力解法时间复杂度 O(m * n)

代码

int strStr(char* haystack, char* needle) {int len_h = strlen(haystack);int len_n = strlen(needle);if (len_n == 0) return 0;  // 如果needle是空字符串,按照题意应返回0if (len_h < len_n) return -1;// 注意这里循环条件改为 <= for (int head = 0; head <= (len_h - len_n); head++) {if (haystack[head] == needle[0]) {int i;// 尝试匹配整个needlefor (i = 0; i < len_n; i++) {if (haystack[head + i] != needle[i]) {break;  // 不匹配,跳出内层循环}}// 如果i等于len_n,说明完全匹配if (i == len_n) {return head;}}}return -1;  // 未找到匹配
}

改进代码

KMP算法

KMP算法核心思想

部分匹配表(Next数组):预处理模式串,构建一个数组记录当匹配失败时,模式串应该回退到的位置。
避免回溯:利用已知信息,当匹配失败时,不必将模式串回退到起点,而是根据部分匹配表回退到合适位置。

详细工作原理

构建Next数组:

  • Next[i]表示当第i个字符匹配失败时,模式串应该回退到的位置
  • 它实际上记录了模式串中前缀和后缀的最长公共元素长度

匹配过程:

  • 主串索引i不回退,只前进
  • 当匹配失败时,根据Next数组调整模式串索引j的位置
  • 这样避免了重复比较已知不会匹配的部分
// 构建Next数组
void buildNext(char* pattern, int* next, int len) {// 初始化int j = 0;next[j] = 0;/* j:指向前缀末尾位置,同时j也表示i之前的子串的最长相等前后缀的长度i:指向后缀末尾位置*/for(int i = 1; i < len; i++){// 处理不相等的情况 -> 让j进行回退while(j > 0 && pattern[j] != pattern[i]){j = next[j - 1];}/*回退结束有两种情况:1.找到最长相等前后缀的位置了。2.没有相等的前后缀,此时j=0*/if(pattern[j] == pattern[i])    {j++;}next[i] = j;}
}// KMP匹配函数
int strStr(char* haystack, char* needle) {if (!needle[0]) return 0;  // 空模式串匹配任何位置int len_h = strlen(haystack);int len_n = strlen(needle);if (len_h < len_n) return -1;// 创建并初始化Next数组int* next = (int*)malloc(sizeof(int) * len_n);buildNext(needle, next, len_n);// 进行匹配int i = 0;  // 主串索引int j = 0;  // 模式串索引while (i < len_h && j < len_n) {if (haystack[i] == needle[j]) {i++;j++;} else if (j > 0) {j = next[j-1];  // 根据Next数组调整模式串索引} else {i++;}}free(next);  // 释放内存// 如果j等于len_n,说明找到完全匹配if (j == len_n) {return i - j;}return -1;  // 未找到匹配
}
http://www.dtcms.com/a/294292.html

相关文章:

  • vue3中el-table表头筛选
  • Flink 状态管理设计详解:StateBackend、State、RocksDB和Namespace
  • 谷粒商城篇章13--P340-P360--k8s/KubeSphere【高可用集群篇一】
  • 抖音集团基于Flink的亿级RPS实时计算优化实践
  • k8s pvc是否可绑定在多个pod上
  • 飞算JavaAI:从“工具革命”到“认知革命”——开发者如何借力AI重构技术竞争力
  • SpringBoot 内嵌 Tomcat 的相关配置
  • MySQL binlog解析
  • linux c语言进阶 - 线程,通信方式,安全方式(多并发)
  • Linux中常见的中英文单词对照表
  • 低代码中的统计模型是什么?有什么作用?
  • 第一二章知识点
  • 交换机的六种常见连接方式配置(基于华为eNSP)
  • 洛谷刷题7.23
  • 电子公章怎么弄到合同上?2025最新指南
  • Android NDK与JNI深度解析
  • 为什么本地ip记录成0.0.0.1
  • 观影《长安的荔枝》有感:SwiftUI 中像“荔枝转运”的关键技术及启示
  • SpringMVC快速入门之请求与响应
  • TODAY()-WEEKDAY(TODAY(),2)+1
  • BEVDet-4D 代码详细解析
  • 《汇编语言:基于X86处理器》第9章 复习题和练习
  • Linux内存映射原理
  • 基于MCP架构的LLM-Agent融合—构建AI Agent的技术体系与落地实践
  • day060-zabbix监控各种客户端
  • 力扣MySQL(1)
  • python 字符串常用处理函数
  • Zookeeper学习专栏(七):集群监控与管理
  • 解决代码生成过程虚拟总线信号无法直接传递给自定义总线信号问题的方法
  • Python curl_cffi库详解:从入门到精通