alefein
alefein

Reputation: 13

java.lang.StringIndexOutOfBoundsException: String index out of range: -1 (Works with another program)

I'm supposed to create a program that finds the longest palindrome in a DNA string. Unlike a regular palindrome program, this one requires A to match with T and C to match with G (so instead of 1221 we'd have TCGA for example). After trying myself I did find a very good program for the normal palindrome problem, the one on this website: http://www.journaldev.com/530/java-program-to-find-out-longest-palindrome-in-a-string

I then tried to modify it to fit my needs. Basically the changes I made were the following:

  1. Instead of those strings shown in the example, I read a string from the argument line. The string is the following DNA sequence (although I tested the program with only parts of it):

http://introcs.cs.princeton.edu/java/31datatype/genomeVirus.txt

  1. Instead of the command

     while (left >= 0 && right < s.length()
                && s.charAt(left) == s.charAt(right)) {
            left--;
            right++;
        }
    

I did:

while (left >= 0 && right < s.length()
&& s.charAt(left) == 'A' && s.charAt(right) == 'T' || s.charAt(left) == 'T' && s.charAt(right) == 'A'
|| s.charAt(left) == 'G' && s.charAt(right) == 'C' || s.charAt(left) == 'C' && s.charAt(right) == 'G')
   {
 left--;
 right++;

(Full code below)

However, when I try this program on a string, I always get the error:

java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.substring(Unknown Source)
    at LongestPalindrome.intermediatePalindrome(LongestPalindrome.java:17)
    at LongestPalindrome.longestPalindromeString(LongestPalindrome.java:26)
    at LongestPalindrome.main(LongestPalindrome.java:5)

I just don't get it! I don't realize how I'm getting out of the string, when I try the original program I linked to, it always works with no matter which string. I feel like I'm doing everything correctly, simply replacing the == command with various scenarios that should make sense.

I figured it might have something to do with

return s.substring(left+1, right);"

I tried to take the +1 away but it seems to ruin the whole deal. I just don't realize how I'm going out of the string, since it worked perfectly before my adjustments.

Any help would be greatly appreciated! Below is the code!

public class LongestPalindrome {

 public static void main(String[] args) {
   String gen = new String(args[0]);
   System.out.println(longestPalindromeString(gen));
 }

 static public String intermediatePalindrome(String s, int left, int right)     {
  if (left > right) return null;
  while (left >= 0 && right < s.length()
    && s.charAt(left) == 'A' && s.charAt(right) == 'T' || s.charAt(left) == 'T' && s.charAt(right) == 'A'
|| s.charAt(left) == 'G' && s.charAt(right) == 'C' || s.charAt(left) == 'C' && s.charAt(right) == 'G')
       {
   left--;
   right++;
  }
  return s.substring(left+1, right);
 }

 // O(n^2)
 public static String longestPalindromeString(String s) {
  if (s == null) return null;
  String longest = s.substring(0, 1);
  for (int i = 0; i < s.length() - 1; i++) {
   //odd cases like 121
   String palindrome = intermediatePalindrome(s, i, i);
    if (palindrome.length() > longest.length()) {
    longest = palindrome;
   }
   //even cases like 1221
   palindrome = intermediatePalindrome(s, i, i + 1);
   if (palindrome.length() > longest.length()) {
    longest = palindrome;
   }
  }
  return longest;
 }

}

Upvotes: 0

Views: 1836

Answers (1)

user207421
user207421

Reputation: 310913

  1. You are calling it with right == 0. You need to change the first call to:

     String palindrome = intermediatePalindrome(s, i, i+1)
    
  2. Operator precedence problem. You've added some || conditions which are also evaluated even if the range checks fail. It should be:

    while (left >= 0 && right < s.length()
    && (s.charAt(left) == 'A' && s.charAt(right) == 'T'
        || s.charAt(left) == 'T' && s.charAt(right) == 'A'
        || s.charAt(left) == 'G' && s.charAt(right) == 'C'
        || s.charAt(left) == 'C' && s.charAt(right) == 'G'))
    

Note the parentheses around the entire second operand of the second &&.

Upvotes: 2

Related Questions