题目
获取两个字符串中最大相同字串,比如:
- str1 = “abcwerthelloyuiodef”,
- str2 = “cvhellobnm”
- 提示:
- 将短的那个串,进行长度依次递减的字串与较长的字串进行比较
题解
这里先分析 两个字符串只有一个最大相同子串的情况:
(1)思路分析:
只有一个最大相同最子串的情况下:
---->跟找最大公约数的算法类似:先确定str1、str2哪个更短一下, 拿短的去比较深蓝色文字
比较的具体情况为:假设有:
- str1 = “abcwerthelloyuiodef”,
- str2 = “cvhellobnm”(length==10)
----利用string的contains(CharSequence s),判断maxstr中,是否包含每次的minstr(str2自己或者子串,具体的minstr是什么进行比对,取决于是哪一趟比较):
- (1)整体的话,因为str2长度为10,则有10大轮的比较(每一轮结束minstr-1,即minstr的长度减少1)
- (2)每一大轮中,具体的-1的情况也不太一样:
- minstr的初值为str2:cvhellobnm
- ①如果第一轮结束之后,contains()的返回值为false,将minstr的长度-1。
- 完成length-1操作之后,对于下一次要进行contains()的minstr有2种情况:
- cvhellobn 或者 vhellobnm
- ②如果第二轮结束之后,contains()的返回值为false,将minstr的长度-1。
- 在①的基础上,完成length-1操作之后,对于下一次要进行contains()的minstr有4种情况:
- cvhellob、vhellobn 或者 vhellobn、hellobnm
- 也即,每次进行length-1 的操作,有两种可能:
- 从当前minstr的首部-1,或者从当前minstr的尾部-1
- –>设置两个指针,来完成这个功能:
- start、end
(2)实现主要功能的代码块:
/*
* 将短的那个串,进行长度依次递减的字串与较长的字串进行比较 外层循环控制的是:一共可以length-1进行多少次(第一次不进行-1,直接比较)
*/
for (int i = 0; i < minString.length(); i++) {
/*
* 因为 substring()的截取区间是左开右闭, 所以,end指针应该指向当前minstring字符串最后一个元素对应的char[]中的索引的后一个位置
* ---- 在这里,将length-1操作设置为:先减去尾部的长度为i的char,依次是倒数第二个...
* 也即,减去后的substring顺序为(从第一大轮开始):
* cvhellobnm-->cvhellobn--vhellobnm-->cvhellob--vhellobn(--cvhellob,出现过这种情况)--
* hellobnm-->...
*/
for (int start = 0, end = minString.length() - i; end <= minString.length(); start++, end++) {
// 因为length-1 可能是从左侧划掉一个char,也可能是从右侧。
// 并且,minstring与循环的控制条件有关,所以不应该将对于短的字符串的修改保留在minstring上
String subString = minString.substring(start, end);
if (maxString.contains(subString)) {
/*
* 如果maxstring中包含当前的修改过后的minstring(也就是substring), 由于minstring是从大到小的范围找,
* 那么,此时得到的就是str1、str2的最大子串
*/
return subString;
}
}
}
完整代码
public class MaxSimpleString {
public static void main(String[] args) {
String str1 = "abcwerthelloyuiodef";
String str2 = "cvhellobnm";
//造一个当前类的对象
MaxSimpleString mss = new MaxSimpleString();
String maxSameString = mss.getMaxSameString(str1, str2);
System.out.println(maxSameString);
}
public String getMaxSameString(String str1, String str2) {
//不加这个判断的话,如果str1或者str2有一个为null,下边会出现空指针的异常
if (str1 != null && str2 != null) {
// 先找出哪个串比较短
String maxString = (str1.length() >= str2.length()) ? str1 : str2;
String minString = (str1.length() < str2.length()) ? str1 : str2;
// 需要两层for循环来实现
/*
* 将短的那个串,进行长度依次递减的字串与较长的字串进行比较 外层循环控制的是:一共可以length-1进行多少次(第一次不进行-1,直接比较)
*/
for (int i = 0; i < minString.length(); i++) {
for (int start = 0, end = minString.length() - i; end <= minString.length(); start++, end++) {
// 因为length-1 可能是从左侧划掉一个char,也可能是从右侧。
// 并且,minstring与循环的控制条件有关,所以不应该将对于短的字符串的修改保留在minstring上
String subString = minString.substring(start, end);
if (maxString.contains(subString)) {
return subString;
}
}
}
}
return null;
}
}
拓展
对于两个字符串中的最大子串有多个的情况,可以参考下面这篇文章:
有多个最大相同子串的情况
I don’t want to let myself down!