题解 | #密码截取#
密码截取
https://www.nowcoder.com/practice/3cd4621963e8454594f00199f4536bb1
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
//主要思路:
//回文在反向排列后不变,
//所以先将原字符串str反向排列,得到str_;
//然后利用contains方法,筛选能够通过str_.contains()的str的子字符串,并记录最大长度maxlen;
//注意,有一类字符串并不是回文,但也能通过上述筛选,那就是str中本就存在的一对逆序字符串 如abcd 和 dcba
//这一类字符串的长度不应该计入maxlen中,通过【自身逆序排列后和原字符串不相同】的方法筛除;
//要注意子串起点和终点的迭代方式,不能跳过任何一个字符,否则可能会导致密码遗漏
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextLine()) { // 注意 while 处理多个 case
String str = in.nextLine();
StringBuilder strReverse = new StringBuilder(str);
strReverse = strReverse.reverse(); //利用sb类翻转字符
String str_ = strReverse.toString(); //反转后切换回string
int l = 0; //str子串起始点在原字符串中的索引
int r = 1;//str子串终点再后一个位置在原字符串中的索引
int maxLen = 1;//最大长度,这个会不断迭代
String strNow; //每次筛选出的新密码
while (r <= str.length()) {
strNow = str.substring(l, r);
if (str_.contains(strNow)) {
//如果新密码字符串的长度不超过目前的最大值,或者新密码字符串并不是回文,那么maxLen不迭代
if ((strNow.length()>maxLen) && test(strNow)) maxLen=Math.max(maxLen,strNow.length());
//只要当前字符串满足contains,那么r就加1,l不变
r++;
} else {
//只要当前字符串不满足contains,那么r不变,l加1
//不用担心l>=r的情况,因为当r=l+1时,选出的子串为一个字母,而一个字母必然通过contains,r就会加1
//所以l和r之间的最小数值差就是1
//注意l和r每次变化值只能是1,否则会遗漏情况,导致不能完整记录所有密码的长度
l++;
}
}
System.out.println(maxLen);
}
}
//test函数用于判断一字符串是否为回文,用于区分特殊情况 例如:原字符中可能同时存在 abcde 和 edcba,
//仅通过逆序对比会把此类字符串也当做密码
static private boolean test(String str0) {
StringBuilder strReverse = new StringBuilder(str0);
strReverse = strReverse.reverse(); //利用sb类翻转字符
String str1 = strReverse.toString(); //反转后切换回string
return str1.equals(str0);
}
}