【算法训练记录——Day09】

●28. 实现 strStr()
●459.重复的子字符串
●字符串总结
●双指针回顾

28.实现strStr()

在这里插入图片描述
思路:联系KMP算法,求解next数组
(next数组)前缀表:起始位置到下标i之前(包括i)的子串中,有多大长度的相同前缀后缀。

  1. next数组含义:next[j]表示模式串第 j 位前最长前缀等于后缀的长度。
  2. 求解next数组,要清楚流程:首先i表示前缀末尾,j表示后缀末尾
    从 j = 0 开始,i = 1 此时前后缀才有意义;
    解决 不匹配怎么办, 匹配怎么办, 更新数组三个步骤
	void getNext(const string& s, vector<int>& next) {
		int j = 0;
		for(int i = 1; i  < s.size(); i++) { // 
			while(j > 0 && s[i] != s[j]) { // 不匹配怎么办
				j = next[j - 1]; // 不匹配向前回退,next[j-1]是当前已经完成匹配的最长相等前后缀, 因此直接回退到这里
			}
			if (s[i] == s[j]) // 匹配怎么办
				j++;          // 匹配上向后延伸
			next[i] = j;      // 更新next数组值
		}
		return;
	}

怎么用next数组?就是和求next数组差不多的用法

	int strStr(string haystack, string needle) {
		if (needle.size() == 0) {
            return 0;
        }
		vector<int> next(needle.size());
		getNext(needle, next);
		int j = 0;
		for(int i = 0; i < haystack.size(); i++) {
			while(j > 0 && haystack[i] != needle[j]) { // 不匹配怎么办
				j = next[j-1];	
			}
			if(haystack[i] == needle[j]) { // 匹配怎么办
				j++;	
			}
			if(j == needle.size()) { // 什么时候结束
				return i - needle.size() + 1;
			}
		}
        return -1;
	}

459.重复的子字符串

在这里插入图片描述
思路:kmp算法的一次应用?
模式串的特质是最长相等前后缀,如果它可以由字串重复多次构成,那子串应该是这个前后缀的子集
好家伙,最长相等前后缀不包含的子串就是重复的子串。为啥,我再看看

解法一:若由重复子串构成,头尾相接一定有原串。
一个原串可以看作多个子串相接,即 aa aaa aaaa ,x = n a 那么头尾相接一定还可以组成新的原串理由就是 2n-2 >= n (n>1)
	bool repeatedSubstringPattern(string s) {
        string t = s + s;
        t.erase(t.begin());
        t.erase(t.end()-1);
        if(t.find(s) != -1)
            return true;
        return false;
    }

解法二:重复子串是最长相等前后缀不包含的那个。直接记结论,也没难记的。就当练习一下next数组求解吧。

	void getNext(const string& s, vector<int>& next){
			int j = 0; // j 表示前缀尾
			next[0] = j;
			for(int i = 1; i < s.size(); i++) { // i 是后缀末尾,i不能为0,否则无前后缀
				while(j > 0 && s[i] != s[j]) { // 不匹配怎么办
					j = next[j-1]; // next[j-1]是已经完成匹配的位置	
				}
				if(s[i] == s[j])
					++j;
				next[i] = j;
			}
			return;
	}
	bool repeatedSubstringPattern(string s) {
		int len = s.size();
		vector<int> next(len);
		getNext(s, next);
		if(next[len-1] != 0 && len % (len-next[len-1]) == 0)
			return true;
		return false;
	}
  • 26
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值