一、找出字符串中第一个匹配项的下标
题目:找出字符串中第一个匹配项的下标
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1
。
输入:haystack = "sadbutsad", needle = "sad" 输出:0 解释:"sad" 在下标 0 和 6 处匹配。 第一个匹配项的下标是 0 ,所以返回 0 。
输入:haystack = "leetcode", needle = "leeto" 输出:-1 解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
思路:
1.暴力想法
直接开始匹配,如果失败重新匹配,如果成功返回下标。
代码如下:
public int strStr(String haystack, String needle) {
int n=needle.length();
//如果needle的长度等于0,则一定为haystack的子串
if(n==0)
return 0;
int m=haystack.length();
//如果m<n表示一定匹配不上
if(m<n)
return -1;
int i=0;
int j=0;
//首字母最大到达m-n位置
while(i<m-n+1){
//寻找首字母
while(i<m&&haystack.charAt(i)!=needle.charAt(j))
i++;
//如果找到尾部则返回-1
if(i==m)
return -1;
//首字母匹配成功,指针同时右移
i++;
j++;
//相等且不越界时,指针同时移动
while(i<m&&j<n&&haystack.charAt(i)==needle.charAt(j)){
i++;
j++;
}
//当needle全部走完,直接返回所需下标
if(j==n){
return i-j;
}else{//否则i要移动到首字母的下一位,j再赋值0
i-=j-1;
j=0;
}
}
return -1;
}
2.KMP
利用KMP算法,得到needel字符串的前缀表,节约匹配项,能够更快的完成所需要的匹配工作,节省时间。由原先的O(m*n)节省到现在的O(m+n)。
代码如下:
public int strStr(String haystack, String needle) {
if(needle.length()==0)
return 0;
//创建前缀表next数组
int[] next=new int[needle.length()];
//得到前缀表
getNext(next,needle);
int j=0;
for (int i = 0; i < haystack.length(); i++) {
while(j>0&&haystack.charAt(i)!=needle.charAt(j)){
j=next[j-1];
}
if(haystack.charAt(i)==needle.charAt(j))
j++;
if(j==needle.length())
return i-j+1;
}
return -1;
}
private void getNext(int[] next, String s) {
int j=0;
next[0]=0;
for (int i = 1; i < next.length; i++) {
//当j>0时,但此时字符不同,j=next[j-1],继续判断值是否相同
while(j>0&&s.charAt(i)!=s.charAt(j))
j=next[j-1];
if(s.charAt(i)==s.charAt(j))
j++;
next[i]=j;
}
}
二、重复的子字符串
题目:重复的子字符串
给定一个非空的字符串 s
,检查是否可以通过由它的一个子串重复多次构成。
输入: s = "abab" 输出: true 解释: 可由子串 "ab" 重复两次构成。
思路:
利用KMP
得出next数组找到最长相等前后缀的长度是多少,用字符串的长度%(字符串长度-最长相等前后缀的长度)如果等于0,证明有子串可以重复多次构成,且长度为(字符串长度-最长相等前后缀的长度)
代码如下:
public boolean repeatedSubstringPattern(String s) {
if(s.equals(" ")) return false;
int len=s.length();
int[] next=new int[len];
int j=0;
next[0]=0;
for (int i = 1; i < len; i++) {
while(j>0&&s.charAt(i)!=s.charAt(j))
j=next[j-1];
if(s.charAt(i)==s.charAt(j))
j++;
next[i]=j;
}
if(next[len-1]>0&&len%(len-next[len-1])==0)
return true;
return false;
}
总结
杨康的第二天,身体是真的虚,今天状态依旧不在线啊,这新冠太猛了,这和发烧根本是在一个水平线上,继续回复吧,加油!