-
- 实现 strStr()
- 459.重复的子字符串
实现strStr()
可以说是暴力解。但是里面的处理比一开始自己写的冗余逻辑要好
class Solution {public int strStr(String haystack, String needle) {char[] strh = haystack.toCharArray();char[] strn = needle.toCharArray();//优化1.没必要全部扫描完。因为最后一部分如果没有子串长那没有比较的意义,所以用字符串的长度减子串的长度。//模拟:abcdef , cde//这里取不取等是要自己算一下的。上例看来,i=3是有意义的,所以取等for (int i = 0; i <= strh.length - strn.length; i++) {int j = 0;//这个条件优化,就是我当时没想到的一个思维,我直接在i的基础上开始用j逐渐+1就可以了。并且两个字符串比较的过程我也包含在里面。这里用while比用if更省事,这是我一开始也没想到的。while (j < strn.length && i + j < strh.length && strh[i + j] == strn[j]) {j++;}//如果这里判断通过了,说明找到子串了。if (j == strn.length) {return i;}}return -1;}
}
重复的子字符串
首先题意是:给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
思路:看到这个话要这么想,如果一个字符串s包含一个重复的字串,那么说明我可以多次移位和换行该字符串,并使其与原始字符串匹配。一定要这么想,如果你想去挨个的枚举扫一遍,那我只能说是麻烦中的麻烦。
比如abcabc
移位一次cabcab
移位两次bcabca
移位三次abcabc
这就是发现的规律。
但是存在一个问题,这个移动的次数存在不确定。而且每次移动都要进行匹配是否是相同字符串,这里又有一部分开销。
所以有没有什么方法,能够把这些开销降下来。回答是有的,这也是这个题的解法。
解法:
1.创建一个新的字符串,str。将s与自身拼接。即str=s+s。
2.然后从str中去掉第一个和最后一个字符,得到str.substring(1,str.length()-1)
3.最后,检查这个新的字符串是否包含原始的s。
核心思想:
如果 s 由重复的子串构成,那么在 s + s 中,去掉首尾字符后,一定还能找到一个完整的 s。
为什么这个方法有效?
如果 s 是由重复子串构成的,那么在 s + s 中,原来的 s 会出现至少两次(除了首尾各少一个字符的情况)。
去掉首尾字符后,如果原来的模式是重复的,那么仍然会保留至少一个完整的 s。
如果 s 不是由重复子串构成的,那么在去掉首尾字符后的字符串中,就不可能找到一个完整的 s。
时间和空间都是o(n)。与kmp时间量级是相同的,但是kmp效率要更高一点,因为他更简洁。
class Solution {public boolean repeatedSubstringPattern(String s) {String str = s + s;return str.substring(1,str.length()-1).contains(s);}
}