Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java USACO Calf Flac回文超时_Java_Optimization_Palindrome - Fatal编程技术网

Java USACO Calf Flac回文超时

Java USACO Calf Flac回文超时,java,optimization,palindrome,Java,Optimization,Palindrome,以下是问题陈述: 测试回文时,忽略标点、空格、数字和大小写,但保留这些额外字符,以便您可以将它们打印出来作为答案;请考虑字母 -Z”和< /代码> -Z’. 查找长度不超过20000个字符的字符串中最大的回文。在删除空格和标点符号之前,最大回文保证最多为2000个字符 输出的第一行应该是找到的最长回文的长度。下一行或多行应该是打印在一行上的回文的实际文本(没有任何周围的空格或标点符号,但包含所有其他字符)(如果回文文本中包含换行符,则多行)。如果有多个长度最长的回文,则输出第一个出现的回文 我

以下是问题陈述: 测试回文时,忽略标点、空格、数字和大小写,但保留这些额外字符,以便您可以将它们打印出来作为答案;请考虑字母<代码> -Z”和< /代码> -Z’.

查找长度不超过20000个字符的字符串中最大的回文。在删除空格和标点符号之前,最大回文保证最多为2000个字符

输出的第一行应该是找到的最长回文的长度。下一行或多行应该是打印在一行上的回文的实际文本(没有任何周围的空格或标点符号,但包含所有其他字符)(如果回文文本中包含换行符,则多行)。如果有多个长度最长的回文,则输出第一个出现的回文

我尝试只使用字母遍历字符串,并测试I(奇数长度)或I和I-1(偶数长度)是否是palidone的中间。我的代码可以工作,但速度太慢,在10个测试用例中的第8个中超时。目前,测试需要1.9秒,最大限制为1秒

我的代码

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;
}