子串和子数组都是连续的;子序列可以不是连续的;
indexOf()底层和KMP几乎一样;只是没有匹配到的时候,返回-1;
public class KMP1 {
public static void main(String[] args) {
String str = "abcrr123tyeererre";
String s = "123";
System.out.println(process(str, s));
//indexOf()
int aaa = str.indexOf(s);
System.out.println(aaa);
}
//朴素匹配算法
public static int process(String str,String s){
int i=0;//i为最后匹配到的在str上的位置;
int j=0;
int a=-1;//为s与str匹配上的在str的第一个字符的位置;
while(i<str.length()&&j<s.length()){
if (str.charAt(i)==s.charAt(j)){
i++;
j++;
}else {
i=i-j+1;
j=0;
}
if (j>=s.length()-1){
a= i-j;
break;
}
}
return a;
}
}
题目:
// 给定两个字符串s1和s2,问s2最少删除多少字符可以成为s1的子串?
// 比如 s1 = “abcde”,s2 = “axbc”
// 返回 1
给定两个字符串s1和s2,问s2最少删除多少字符可以成为s1的子串?
// 比如 s1 = "abcde",s2 = "axbc"
// 返回 1
// 解法一,来自群里的解法:
// 求出str2所有的子序列,然后按照长度排序,长度大的排在前面。
// 然后考察哪个子序列字符串和s1的某个子串相等(KMP),答案就出来了。
// 分析:
// 因为题目原本的样本数据中,有特别说明s2的长度很小。所以这么做也没有太大问题,也几乎不会超时。
// 但是如果某一次考试给定的s2长度远大于s1,这么做就不合适了。
public static int minCost1(String s1, String s2) {
List<String> s2Subs = new ArrayList<>();
process(s2.toCharArray(), 0, "", s2Subs);
s2Subs.sort(new LenComp());
for (String str : s2Subs) {
if (s1.indexOf(str) != -1) { // indexOf底层和KMP算法代价几乎一样,也可以用KMP代替
return s2.length() - str.length();
}
}
return s2.length();
}
public static void process(char[] str2, int index, String path, List<String> list) {
if (index == str2.length) {
list.add(path);
return;
}
process(str2, index + 1, path, list);
process(str2, index + 1, path + str2[index], list);
}
public static class LenComp implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return o2.length() - o1.length();
}
}
public static int kmp(String str, String dest){
//1.首先计算出 部分匹配表
int[] next = kmpnext(dest);
System.out.println("next ="+Arrays.toString(next));
//2.查找匹配位置
for(int i = 0, j = 0; i < str.length(); i++){
while(j > 0 && str.charAt(i) != dest.charAt(j)){
j = next[j-1];
}
if(str.charAt(i) == dest.charAt(j)){
j++;
}
if(j == dest.length()){
return i-j+1;
}
}
return -1;
}
/**
* 计算部分匹配表
*/
public static int[] kmpnext(String dest){
int[] next = new int[dest.length()];
next[0] = 0;
for(int i = 1,j = 0; i < dest.length(); i++){
while(j > 0 && dest.charAt(j) != dest.charAt(i)){
j = next[j - 1];
}
if(dest.charAt(i) == dest.charAt(j)){
j++;
}
next[i] = j;
}
return next;
}
如果是最长回文子串是那个;看力扣解题;o(N2);用动态规划解题的,也能用马拉车解;
也可以用中心扩展法,加上#号后,求长度;能达到o(N2) 可以求长度或者回文子串;
public static char[] manacherString(String str){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
sb.append("#");
sb.append(str.charAt(i));
}
sb.append("#");
return sb.toString().toCharArray();
}
//直接调用这个函数就行;求出最长的子串长度;
public static int manacher(String str){
if(str == null || str.length() < 1){
return 0;
}
char[] charArr = manacherString(str);
int[] radius = new int[charArr.length];
int R = -1;
int c = -1;
int max = Integer.MIN_VALUE;
for (int i = 0; i < radius.length; i++) {
radius[i] = R > i ? Math.min(radius[2*c-i],R-i+1):1;
while(i+radius[i] < charArr.length && i - radius[i] > -1){
if(charArr[i-radius[i]] == charArr[i+radius[i]]){
radius[i]++;
}else{
break;
}
}
if(i + radius[i] > R){
R = i + radius[i]-1;
c = i;
}
max = Math.max(max,radius[i]);
}
return max-1;
}
小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的。所以小A只想知道给定的一个字符串的最大回文子串是多少,但是小A对这个结果并不是非常满意。现在小A可以对这个字符串做一些改动,他可以把这个字符串最前面的某一段连续的字符(不改变顺序)移动到原先字符串的末尾。那么请问小A通过这样的操作之后(也可以选择不移动)能够得到最大回文子串的长度是多少。
import java.util.*;
public class Main {
public static void main(String... args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String str = s + s;
int ans = manacher(str);
//ans = Math.min(ans, s.length());
System.out.println(ans);
}
public static char[] manacherString(String str){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
sb.append("#");
sb.append(str.charAt(i));
}
sb.append("#");
return sb.toString().toCharArray();
}
//直接调用这个函数就行;求出最长的子串长度;
public static int manacher(String str){
if(str == null || str.length() < 1){
return 0;
}
char[] charArr = manacherString(str);
int[] radius = new int[charArr.length];
int R = -1;
int c = -1;
int max = Integer.MIN_VALUE;
for (int i = 0; i < radius.length; i++) {
radius[i] = R > i ? Math.min(radius[2*c-i],R-i+1):1;
while(i+radius[i] < charArr.length && i - radius[i] > -1){
if(charArr[i-radius[i]] == charArr[i+radius[i]]){
radius[i]++;
}else{
break;
}
}
if(i + radius[i] > R){
R = i + radius[i]-1;
c = i;
}
max = Math.max(max,radius[i]);
}
return max-1;
}
}