当前位置:网站首页>数组与字符串10-实现 strStr()
数组与字符串10-实现 strStr()
2022-08-03 05:25:00 【花开花落夏】
使用KMP算法实现 strStr()
一 题目
源自leetcode官网
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。
说明:当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。二 暴力破解法
对于此题,可以使用暴力破解法。如上图所示,将needle的第一个字符依次与haystack中的字符比较,若不相等,则换成haystack中的第二个字符,若相等,则将needle的第二个字符与haystack比较字符的下一个字符相比较。若needle中所有字符都已经比较完成且等于haystack相对位置的字符,则找到答案。
代码:
class Solution {
public int strStr(String haystack, String needle) {
int index = -1;
if(needle.isBlank()){
index = 0;
} else {
char[] hay = haystack.toCharArray();
char[] need = needle.toCharArray();
for(int i = 0;i<hay.length;i++){
int j=0, tmp = i;
while (j<needle.length()&&tmp<hay.length&&hay[tmp]==need[j]){
tmp++;
j++;
}
if(j>=needle.length()){
index=i;
break;
}
}
}
return index;
}
}
运行结果:运行效率太低。
三 使用KMP算法来求解
KMP算法是一种改进的字符串匹配算法。其核心思想是:根据公共前后缀为needle字符串创建一个回退数组next.
如下图所示:到红框位置,字符串needle与haystack不匹配。按暴力破解法,应从haystack字符串的第二个字符开始,重新与needle的第一个字符相比较。但我们观察这两个字符串可知,橙色框的字符与蓝色框的字符相匹配,且对于needle字符串,C之前的字符,蓝色框与绿色框的字符串相等。因此可以等价于橙色框已经和绿色框做了比较,此时,我们可以将橙色框的下一个字符与绿色框的下一个字符比较。若相等,则字符继续往下移动,不相等,就再找匹配字符串。为了知道每次不匹配时,我们应该回退到needle字符串哪里,便为needle字符串创建一个next数组。next数组为int[] next,数组的索引为needle字符串索引,值为应该回退的位置。将needle转化为字符数组,对于needle[i],能回退的位置为needle[0]到needle[i-1]之后最大的公共前后缀+1的位置。对于下图所示的needle,对于c字符串所在的位置,其needle[0]到needle[i-1]为ababa,前缀有: a, ab,aba,abab,后缀有:baba,aba,ba,a,因此最大公共前后缀为aba。此时next[5]=3。
对于next数组,有两个特征,若needle[j+1]最大值为next[j]+1.若next[j+1]不等于needle[next[j]+1],则next[j+1]可能的最大值为next[next[j]]+1。依次类推。可以得到next数组。
class Solution {
public int strStr(String haystack, String needle) {
int index = -1;
if(needle.isBlank()){
index = 0;
} else {
int[] next = new int[needle.length()];
createNext(next,needle);
int i = 0;
int j =0;
while (j<needle.length() && i<haystack.length()){
if(haystack.charAt(i)==needle.charAt(j)){
i++;
j++;
}else{
j=next[j];
if(j==-1){
i++;
j++;
}
}
}
if(j>=needle.length()){
index = i-j;
}
}
return index;
}
private void createNext(int[] next,String needle){
char[] tmp = needle.toCharArray();
next[0] = -1;
int i = 0,j=-1;
while(i<needle.length()-1){
if(j==-1 || tmp[i]==tmp[j]){
next[++i]=++j;
}else{
j=next[j];
}
}
}
}
运行结果:
边栏推荐
- Delightful Nuxt3 Tutorial (2): Build a Blog Quickly and Easily
- 2021-03-22
- Automatic ticket issuance based on direct reduction of China Southern Airlines app
- 自监督论文阅读笔记: MoCoV2使用动量对比学习改进基线
- NIO知识汇总 收藏这一篇就够了!!!
- 设备树解析源码分析<devicetree>-1.基础结构
- window下VS2022封装静态库以及调用静态库
- 梯度下降、反向传播
- 常见的电子元器件分类介绍-唯样商城
- classpath:与classpath*的比较
猜你喜欢
随机推荐
自监督论文阅读笔记 DetCo: Unsupervised Contrastive Learning for Object Detection
虚拟地址空间布局
ZEMAX | 在设计抬头显示器(HUD)时需要使用哪些工具?
六、对比Vector、ArrayList、LinkedList有何区别?(设计、性能、安全)
【第四周】MobileNet和HybridSN
Difference between @JsonProperty and JSONField?
A.1#【内存管理】——1.1.2 zone: struct zone
C# 数组之回溯法
三、final、finally、 finalize有什么不同?
window下VS2022封装静态库以及调用静态库
快速的将结构体各成员清零
观看华为AI技术领域课程--深度学习前三章总结
g++参数说明
ZEMAX | 探索 OpticStudio中的序列模式
借助ginput函数在figure窗口实时读取、展示多条曲线的坐标值
设备树(devicetree)-dts语法
KASLR-内核地址空间布局随机化
enum和enum class的区别
深度学习理论课程第八、九、十章总结
ZEMAX | 探究 OpticStudio 偏振分析功能