LC题解-重复的子字符串-KML算法

解题思路

  • KML算法,计算最长相当前后缀长度,字符串长度减最长相当前后缀长度即为最小的重复字符串,字符串长度余最小重复字符串长度为0则说明字符串为重复字符串
  • 将字符串相加,同时掐头去尾2个,如果新字符串包含原字符串,则说明字符串是重复字符串

KML 解题源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public boolean repeatedSubstringPattern(String s) {
if (s == null || s == "" || s.length() == 1) {
return false;
}
int[] next = getNext(s);
int preNextLen = next[next.length - 1];
return preNextLen > 0 && next.length % (next.length - preNextLen) == 0;
}

private int[] getNext(String s) {
char[] sc = s.toCharArray();
int j = 0;

int[] next = new int[s.length()];

for (int i = 1; i < sc.length; i++) {
while (j > 0 && sc[j] != sc[i]) {
j = next[j - 1];
}
if (sc[j] == sc[i]) {
j++;
}
next[i] = j;
}

return next;
}

相加解题源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

public boolean repeatedSubstringPattern(String s) {
if(s == null || s.length() < 2) {
return false;
}
String ns = s + s;
return strStr(ns.substring(1, ns.length() - 1), s) >= 0;
}

private int strStr(String ns, String s) {
int[] next = getNext(s);

char[] nsc = ns.toCharArray();
char[] sc = s.toCharArray();

int j = 0;

for(int i = 0; i < nsc.length; i++) {
while(j > 0 && nsc[i] != sc[j]) {
j = next[j - 1];
}

if(nsc[i] == sc[j]) {
j++;
if(j == sc.length){
return i - (j - 1);
}
}
}

return -1;
}

private int[] getNext(String s) {
int[] next = new int[s.length()];

int j = 0;
char[] cs = s.toCharArray();
for(int i = 1; i < s.length(); i++) {
while(j > 0 && cs[i] != cs[j]) {
j = next[j - 1];
}

if(cs[j] == cs[i]) {
j++;
}

next[i] = j;
}

return next;
}