一、28. 找出字符串中第一个匹配项的下标(串匹配问题)
https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/
class Solution {
public:
//获得模式串的next表 表中的元素值代表与其重复的前缀中最后一个元素的下标(虚拟通配字符 下标-1)
void getnext(int *next,const string &s){
//定义两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置
int i = 0;
int j = -1;
//j所指为通配字符 next表第一个元素值为-1
next[0] = -1;
for(i = 1;i<s.size();i++){//i从1开始,j+1从0开始 刚好错开1位
while(j>=0 && s[i]!=s[j+1]){// 前后缀不相同,j=-1或前后缀相同时跳出循环
j = next[j];// 向前回退
}
if(s[i] == s[j+1]){// 找到相同的前后缀
j++;
}
next[i] = j; // 将j(前缀的长度)赋给next[i]
}
}
int strStr(string haystack, string needle) {
if(needle.size() == 0){
return 0;
}
int next[needle.size()];
//生成next表 next表元素值是所指元素的后缀与前缀重复时,前缀末元素的下标
getnext(next,needle);
int j = -1;
for(int i = 0;i<haystack.size();i++){
//若模式串与文本串所指字符不匹配,进入循环查找匹配项(j!=-1)或通配项(j=-1)
while(j>=0 && haystack[i] != needle[j+1]){
j = next[j];
}
//若匹配,则模式串指针向后移动 比较下一个字符
if(haystack[i]== needle[j+1]){
j++;
}
//模式串指针指向最后一个元素时,返回文本串匹配位置的第一个元素索引
if(j == (needle.size()-1)){
return (i-needle.size()+1);
}
}
return -1;
}
};
https://leetcode.cn/problems/repeated-substring-pattern/
class Solution {
public:
//生成next表
void getnext(int* next,string &s){
int j = -1;
next[0] = -1;
for(int i = 1;i<s.size();i++){
while(j >= 0 && s[i] != s[j+1]){
j = next[j];
}
if(s[i] == s[j+1]){
j++;
}
next[i] = j;
}
}
bool repeatedSubstringPattern(string s) {
//自身子串可以与自身完全匹配多次
//最长前后缀,剩余的元素即为重复元素
//字符串长度要>=2,才会重复
if(s.size() <= 1){
return false;
}
//next表
int next[s.size()];
getnext(next,s);
//如果是重复串,最长前后缀一定出现在末元素
//如果是重复串,前面部分即为重复部分
//如果是非重复串,前后缀的中间部分是非重复部分
//len 为总长度-一个重复子串
int len = s.size()-next[s.size()-1]-1;
//若s是重复子串,len为剩余部分的长度
//若s为非重复子串,len为重复部分+非重复部分的长度
//(2*重复部分+非重复部分) % (重复部分+非重复部分) 是否等于0
//非重复部分=0,则上式=0;非重复部分!=0,上式!=0
if(next[s.size()-1] != -1 && s.size() % len == 0){//next[s.size()-1] != -1 等于-1,代表没有重复前后缀,自然也就不是重复子串
return true;
}
return false;
}
};