28. 实现 strStr()
题目
public int strStr(String s, String p) {
int sLen = s.length();
int pLen = p.length();
for (int i = 0; i < sLen-pLen+1; i++) {
if(isEqual(s.substring(i,i+pLen),p)){
return i;
}
}
return -1;
}
private boolean isEqual(String str, String p) {
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != p.charAt(i)) {
return false;
}
}
return true;
}
public int strStr(String s, String p) {
int now = 0;
int x = 1;
int[] next = new int[p.length()];
next[0] = 0;
while (x < p.length()) {
if (p.charAt(now) == p.charAt(x)) {
now++;
next[x] = now;
x++;
}
else if (now != 0) {
now = next[now-1];
}
else {
next[x] = 0;
x += 1;
}
}
int tar = 0;
int pos = 0;
int sLen = s.length();
int pLen = p.length();
while(tar < sLen) {
if (s.charAt(tar) == p.charAt(pos)) {
if (pos == pLen-1) return tar-pos;
tar++;
pos++;
}
else if (pos != 0) {
pos = next[pos-1];
}
else {
tar++;
}
}
return -1;
}
459.重复的子字符串
题目
private static boolean isEqual(String str, String p) {
if (str.length() != p.length()) return false;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != p.charAt(i)) {
return false;
}
}
return true;
}
public static boolean repeatedSubstringPattern(String s) {
int k = 1;
int group;
while (k <= s.length()/2) {
StringBuilder sb = new StringBuilder();
String p = s.substring(0, k);
group = s.length()/p.length();
for (int j = 0; j < group; j++) {
sb.append(p);
}
System.out.println("group:"+group);
System.out.println("s:"+s+",p:"+sb.toString());
if (isEqual(s,sb.toString())) {
return true;
}
k++;
}
return false;
}
- KMP的next数组方法
- 前面方法超时,因此我们思考,要找重复子字符串,与前缀后缀匹配相关,因此想到next数组
- 通过观察next数组,我们可以发现,若len可以被len-next[len-1]的值整除,则说明都是由重复子字符串构成。
证明
- 假设字符串s使用多个重复子串构成(这个子串是最小重复单位),重复出现的子字符串长度是x,所以s是由n * x组成。
- 因为字符串s的最长相同前后缀的的长度一定是不包含s本身,所以 最长相同前后缀长度必然是m * x,而且 n - m = 1,(这里如果不懂,看上面的推理)
- 所以如果 nx % (n - m)x = 0,就可以判定有重复出现的子字符串。
public static boolean repeatedSubstringPattern(String s) {
int now = 0;
int x = 1;
int[] next = new int[s.length()];
next[0] = 0;
while (x < s.length()) {
if (s.charAt(now) == s.charAt(x)) {
now++;
next[x] = now;
x++;
}
else if (now != 0) {
now = next[now-1];
}
else {
next[x] = 0;
x += 1;
}
}
if (next[s.length() - 1] != 0 && s.length() % (s.length() - (next[s.length() - 1])) == 0) {
return true;
}
return false;
}