Java USACO Calf Flac回文超时
以下是问题陈述: 测试回文时,忽略标点、空格、数字和大小写,但保留这些额外字符,以便您可以将它们打印出来作为答案;请考虑字母<代码> -Z”和< /代码> -Z’. 查找长度不超过20000个字符的字符串中最大的回文。在删除空格和标点符号之前,最大回文保证最多为2000个字符 输出的第一行应该是找到的最长回文的长度。下一行或多行应该是打印在一行上的回文的实际文本(没有任何周围的空格或标点符号,但包含所有其他字符)(如果回文文本中包含换行符,则多行)。如果有多个长度最长的回文,则输出第一个出现的回文 我尝试只使用字母遍历字符串,并测试I(奇数长度)或I和I-1(偶数长度)是否是palidone的中间。我的代码可以工作,但速度太慢,在10个测试用例中的第8个中超时。目前,测试需要1.9秒,最大限制为1秒 我的代码Java USACO Calf Flac回文超时,java,optimization,palindrome,Java,Optimization,Palindrome,以下是问题陈述: 测试回文时,忽略标点、空格、数字和大小写,但保留这些额外字符,以便您可以将它们打印出来作为答案;请考虑字母 -Z”和< /代码> -Z’. 查找长度不超过20000个字符的字符串中最大的回文。在删除空格和标点符号之前,最大回文保证最多为2000个字符 输出的第一行应该是找到的最长回文的长度。下一行或多行应该是打印在一行上的回文的实际文本(没有任何周围的空格或标点符号,但包含所有其他字符)(如果回文文本中包含换行符,则多行)。如果有多个长度最长的回文,则输出第一个出现的回文 我
import java.io.*;
import java.util.*;
class calfflac {
public static void main (String [] args) throws IOException {
BufferedReader f = new BufferedReader(new FileReader("calfflac.in"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("calfflac.out")));
String line = "";
while(true) {
String l = f.readLine();
if(l == null) break;
line += l + "\n";
}
String temp = line;
line = line.toLowerCase();
String rem = "";
ArrayList<Integer> map = new ArrayList<Integer>();
/* Mapping the index of the letter in the String with parsed chars
* to the index of the letter in the original String */
for(int i = 0; i < line.length(); i++) {
if(Character.isLetter(line.charAt(i))) {
map.add(i);
rem += line.substring(i, i + 1);
}
}
int longest = 0; // longest palindrome length
int left = 0; // first char index of the palindrome
int right = 0; // last char index of the palindrome
for(int i = 1; i < rem.length() - longest / 2; i++) {
int[] n = getPali(i, i, rem, longest / 2); // odd length palidrome
if(n[1] - n[0] > longest && n[0] != i) {
longest = n[1] - n[0] + 1;
left = n[0];
right = n[1];
}
n = getPali(i - 1, i, rem, longest / 2); // even length palindrome
if(n[1] - n[0] > longest && n[0] != i - 1) {
longest = n[1] - n[0] + 1;
left = n[0];
right = n[1];
}
}
out.println(longest);
// getting the indices of the first and last char in the original substring and printing it.
out.println(temp.substring(map.get(left), map.get(right) + 1));
out.close();
f.close();
System.exit(0);
}
// checks if a given String is a palindrome
public static boolean isPali(String str) {
for(int i = 0; i < str.length() / 2 + 1; i++) {
if(str.charAt(i) != str.charAt(str.length() - 1 - i)) {
return false;
}
}
return true;
}
/*
* returns the indices of the first and last chars of the largest palindrome with left, right as the middle
* right == left is a palindrome of odd length
* right - left == 1 is a palindrome of even length
*/
public static int[] getPali(int left, int right, String str, int longest) {
if(left - longest < 0 || right + longest >= str.length()) {
return new int[]{left, right};
}
// checks if the String is a palidrome. I think I can somehow delete this check, but not sure how
if(!isPali(str.substring(left - longest, right + longest + 1))) {
return new int[]{left, right};
}
left = left - longest;
right = right + longest;
for(int i = 0; i < str.length() / 2; i++) {
if(left < 0 || right > str.length() - 1) return new int[]{left + 1, right - 1};
if(str.charAt(left) == str.charAt(right)) { // compares the next two chars. Checks inside out
left--;
right++;
} else {
break;
}
}
return new int[]{left + 1, right - 1};
}
}
我想我可以通过某种方式同时处理偶数回文和奇数回文来加快速度,但我不确定如何处理。我也在想,如果回文比我找到的最长的回文短,那么可能不需要测试回文的内部。有人能告诉我如何优化或加快我的代码吗?我认为你把问题复杂化了,我会尽力帮助你,但我的java有点生疏,所以我将以一种非常失落的形式编写代码,我将在编辑中解释我的解决方案
int maxPalindrom(String x){
int max = 0;
int current;
for(int i=0; i<x.length - 1; i++){
current = 1;
for(int j = 1; j < min(x.length - i, i); j ++){
if(x[i-j] == x[i+j])
current += 2;
else
break;
}
if (current > max) current = max;
current = 0;
for(int j = 0; j < min(x.length - i, i); j ++){
if(x[i - j] == x[i + 1 - j])
current += 2;
else
break;
}
if (current > max) current = max;
}
return max;
}
int-maxPalindrom(字符串x){
int max=0;
电流;
对于(int i=0;i max)电流=max;
电流=0;
对于(int j=0;j最大值)电流=最大值;
}
返回最大值;
}
更新
回文可以是aaxaa
或axxa
的形式,因此我将字符串迭代到,并将其移动到第一个内循环的x
和第二个内循环的第一个x
,
我更新current
,直到找到一个能打破回文的案例。
如果current
的值较高,我将更新max
。
通过考虑外部循环中的最大值,可以进一步优化此代码
我希望这会对您有所帮助,如果您还有其他问题,请尽管提。谢谢您的回答。我有相同的理论(对于双嵌套for循环,O(2n^2)),但它仍然太慢。它看起来有点混乱,因为我还必须返回原始字符串。您是否看到重复的不必要的字符串操作?是的,您可以使外部循环停止条件i
int maxPalindrom(String x){
int max = 0;
int current;
for(int i=0; i<x.length - 1; i++){
current = 1;
for(int j = 1; j < min(x.length - i, i); j ++){
if(x[i-j] == x[i+j])
current += 2;
else
break;
}
if (current > max) current = max;
current = 0;
for(int j = 0; j < min(x.length - i, i); j ++){
if(x[i - j] == x[i + 1 - j])
current += 2;
else
break;
}
if (current > max) current = max;
}
return max;
}