目录
459.重复的子字符串
如果暴力枚举算法,则枚举字符串里面所有出现的子串,并且去判断枚举的字符串里面是否包含这个子串。
如果i是子串位置终止处,i<n/2,并且s[j]=s[j-i]。
注意i和j的边界条件
class Solution {
/**
* 暴力法----->s是否是重复字符串
* i枚举子串,s[j]=s[j-i]
*
* @param s
* @return
*/
public boolean repeatedSubstringPattern(String s) {
int len = s.length();
char[] ch = s.toCharArray();
for (int i = 1; i <= (len / 2); i++) {//i标记重复子串的末尾位置
if (len % i == 0) {//不能整除的话,没有意义
boolean flag = true;
for (int j = i; j < len; j++) {
if (ch[j] != ch[j - i]) {
flag = false;
break;
}
}
if (flag) {
return true;
}
}
}
return false;
}
}
如果用kmp算法,首先,如果s是重复子串,则s+s里面刨去本身的s,还能再搜索到s
例如:字符串s:ababab | 字符串ss(s+s):ababab|ababab
很明显可以再找到一个s,又要不包含两者本身那么就掐头去尾。
找重复子串----->双倍掐头去尾------->若能找到则重复
class Solution {
/**
* 库函数----->找重复子串
*
* @param s
* @return
*/
public boolean repeatedSubstringPattern(String s) {
String ss = s + s;
ss = ss.substring(1, ss.length() - 1);//不包括endindex
return ss.contains(s);
}
}
利用kmp算法去做这个搜索,即在s+s掐头去尾的主串里面搜索s这个子串
class Solution {
/**
* 是否为重复子串
*
* @param s
* @return
*/
public boolean repeatedSubstringPattern(String s) {
String ss = s + s;
ss = ss.substring(1, ss.length() - 1);
return KMP(ss, s);
}
/**
* KMP算法
*
* @param mainer
* @param pattern
* @return
*/
public boolean KMP(String mainer, String pattern) {
int len1 = mainer.length();
int len2 = pattern.length();
if (len1 < len2) {
return false;
}
int[] next = getNext(pattern.toCharArray());
int i = 0, j = 0;
while (i < len1 && j < len2) {
if (mainer.charAt(i) == pattern.charAt(j)) {
i++;
j++;
} else if (next[j] == -1) {
i++;
} else {
j = next[j];
}
}
return j == len2;
}
/**
* 求next数组,第一个是-1,第二个是0,然后递推,cn中间量
*
* @return
*/
public int[] getNext(char[] ch) {
if (ch.length == 1) {
return new int[]{-1};
}
int[] next = new int[ch.length];
next[0] = -1;
next[1] = 0;
int cn = 0;
int i = 2;
while (i < ch.length) {
if (ch[i - 1] == ch[cn]) {
next[i++] = ++cn;
} else if (cn > 0) {
cn = next[cn];
} else {
next[i++] = 0;
}
}
return next;
}
}
字符串总结+双指针方法回顾
在字符串章节,常见的库函数比如,valueof,substring,fill,contain等要熟练,并且字符串这边整体翻转然后再局部翻转的思想。
并且字符串的大头KMP算法,包括两大部分,next数组,以及具体查找的时候是怎么跳的,一定要掌握清楚。
双指针算法在翻转字符串,还是滑动窗口这边都有一个广泛的应用,以及去找倒数第k个结点(链表),使用快慢指针的操作要熟练。
2022.10.09补