卡码网55右旋字符串
将字符串中的后面 k 个字符移到字符串的前面
使用StringBuilder 先加入后k个字符,再加入前面的字符。
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
String s = sc.next();
StringBuilder result = new StringBuilder();
result.append(s, s.length()-k, s.length());
result.append(s, 0, s.length()-k);
System.out.println(result);
}
}
28找出字符串中第一个匹配项的下标
使用KMP算法计算next数组,从而得到查找不匹配之后的指针应该指向哪里
public int strStr(String haystack, String needle) {
int n = haystack.length();
int m = needle.length();
int[] kmp = kmp(needle);
int j = -1; // // 因为next数组里记录的起始位置为-1
for (int i = 0; i < n; i++) { // 注意i就从0开始
while(j >= 0 && haystack.charAt(i) != needle.charAt(j+1)) { // 不匹配
j = kmp[j]; // j 寻找之前匹配的位置
}
if (haystack.charAt(i) == needle.charAt(j+1)) { // 匹配,j和i同时向后移动
j++; // i的增加在for循环里
}
if (j == (m - 1) ) { // 文本串s里出现了模式串t
return (i - m + 1);
}
}
return -1;
}
public int[] kmp(String s){
int j = -1;
int[] next = new int[s.length()];
next[0] = -1;
for(int i = 1; i < s.length(); i++) { // 注意i从1开始
while (j >= 0 && s.charAt(i) != s.charAt(j + 1)) { // 前后缀不相同了
j = next[j]; // 向前回退
}
if (s.charAt(i) == s.charAt(j + 1)) { // 找到相同的前后缀
j++;
}
next[i] = j; // 将j(前缀的长度)赋给next[i]
}
return next;
}
459重复的子字符串
使用KMP算法计算next数组,因此由子字符串构成的字符串的next数组,有着特别形式。
即:最后一位的next数组+1,一定大于或等于length/2。——因为字符串是由两个及以上的子字符串构成
最后一位的next数组+1,一定能整除子字符串的个数。——可以排除aabaaba的情况
class Solution {
public int[] kmp(String s){
int j = -1;
int[] next = new int[s.length()];
next[0] = -1;
for(int i = 1; i < s.length(); i++) { // 注意i从1开始
while (j >= 0 && s.charAt(i) != s.charAt(j + 1)) { // 前后缀不相同了
j = next[j]; // 向前回退
}
if (s.charAt(i) == s.charAt(j + 1)) { // 找到相同的前后缀
j++;
}
next[i] = j; // 将j(前缀的长度)赋给next[i]
}
return next;
}
public boolean repeatedSubstringPattern(String s) {
if (s.length()==1){
return false;
}
int[] kmp = kmp(s);
int i = s.length()-1;
if ((kmp[s.length() - 1]+1)>=s.length()/2.0 && (kmp[s.length() - 1]+1)%(s.length()-kmp[s.length() - 1]-1)==0){
return true;
}else {
return false;
}
}
}
收获
在一个串中查找是否出现过另一个串,考虑KMP算法