编写一个函数,返回给定字符串中最长的回文字符串。

104
例如,在字符串“abaccddccefe”中寻找“ccddcc”。
我想到了一种解法,但是它的时间复杂度为O(n^2)。
算法1: 步骤: 这是一种暴力方法 1. 有两个for循环 对于i = 1到i小于array.length-1 对于j=i+1到j小于array.length 2. 这样就可以从数组中获得每个可能组合的子串。 3. 拥有一个回文函数来检查一个字符串是否是回文的。 4. 因此,对于每个子串(i,j),调用此函数,如果它是回文的,则将其存储在一个字符串变量中。 5. 如果你发现下一个回文子串大于当前子串,则用当前子串替换它。 6. 最后,您的字符串变量将具有答案。
问题: 1. 这个算法的时间复杂度为O(n^2)。
算法二: 1. 反转字符串并将其存储在不同的数组中 2. 现在在两个数组之间找到最大匹配的子字符串 3. 但这也需要O(n^2)的时间
你们能想出一个更好的算法吗?如果可能的话,请使用O(n)时间。

44
我认为第一种方法需要O(n^2)的时间来获取所有子字符串,再需要O(n)的时间检查它们是否是回文,总共需要O(n^3)的时间复杂度? - Skylar Saveland
如果我知道我正在处理回文,并将我的字符串保存为两半,那么如果我使用Java,我将拥有O(1)函数检查,对吗? - viki.omega9
10
第二个算法正确吗?那么对于字符串:"abcdecba",最大的匹配子串是什么呢("abcdecba" vs. "abcedcba")? "abc" 或者 "cba"。然而,这两个都不是回文。 - Yarneo
@Learner,只是好奇,在你上面的步骤中,你在for循环中引用了哪个数组?你所指的数组是指字符串吗?string.length? - Zolt
1
对于那些正在寻找O(n^2)答案的人,请参考以下链接:https://www.geeksforgeeks.org/longest-palindrome-substring-set-1/ - Shirish Herwade
显示剩余3条评论
23个回答

0

这个解决方案的时间复杂度为O(n^2)。空间复杂度为O(1)。

public class longestPalindromeInAString {

        public static void main(String[] args) {
            String a =  "xyMADAMpRACECARwl"; 
            String res = "";
            //String longest = a.substring(0,1);
            //System.out.println("longest => " +longest);
            for (int i = 0; i < a.length(); i++) {
                String temp = helper(a,i,i);//even palindrome
                if(temp.length() > res.length()) {res = temp ;}
                temp = helper(a,i,i+1);// odd length palindrome
                if(temp.length() > res.length()) { res = temp ;}

            }//for
            System.out.println(res);
            System.out.println("length of " + res + " is " + res.length());

        }

        private static String helper(String a, int left, int right) {
            while(left>= 0 && right <= a.length() -1  &&  a.charAt(left) == a.charAt(right)) {
                left-- ;right++ ;
            }
            String curr = a.substring(left + 1 , right);
            System.out.println("curr =>" +curr);
            return curr ;
        }

    }

0

这将返回给定字符串中最长的回文字符串

-(BOOL)isPalindromString:(NSString *)strInput
{
    if(strInput.length<=1){
        return NO;
    }
    int halfLenth = (int)strInput.length/2;

    BOOL isPalindrom = YES;
    for(NSInteger i=0; i<halfLenth; i++){

        char a = [strInput characterAtIndex:i];
        char b = [strInput characterAtIndex:(strInput.length-1)-i];

        if(a != b){
            isPalindrom = NO;
            break;
        }
    }
    NSLog(@"-%@- IS Plaindrom %@",strInput,(isPalindrom ? @"YES" : @"NO"));
    return isPalindrom;
}


-(NSString *)longestPalindrom:(NSString *)strInput
{
    if(strInput.length<=1){
        return @"";
    }

    NSString *strMaxPalindrom = @"";

    for(int i = 0; i<strInput.length ; i++){

        for(int j = i; j<strInput.length ; j++){

            NSString *strSub = [strInput substringWithRange:NSMakeRange(i, strInput.length-j)];

            if([self isPalindromString:strSub]){

                if(strSub.length>strMaxPalindrom.length){

                    strMaxPalindrom = strSub;
                }
            }
        }
    }
    NSLog(@"-Max - %@",strMaxPalindrom);
    return strMaxPalindrom;
}

-(void)test
{
    [self longestPalindrom:@"abcccbadeed"];
}

== 输出 ===

输入:abcccde 输出:ccc

输入:abcccbd 输出:bcccb

输入:abedccde 输出:edccde

输入:abcccdeed 输出:deed

输入:abcccbadeed 输出:abcccba


0

尝试使用字符串 - “HYTBCABADEFGHABCDEDCBAGHTFYW123456789987654321ZWETYGDE”; 它应该适用于偶数和奇数的回文。非常感谢Mohit!

使用命名空间std;

string largestPal(string input_str)
{
  string isPal = "";
  string largest = "";
  int j, k;
  for(int i = 0; i < input_str.length() - 1; ++i)
    {
      k = i + 1;
      j = i - 1;

      // starting a new interation                                                      
      // check to see if even pal                                                       
      if(j >= 0 && k < input_str.length()) {
        if(input_str[i] == input_str[j])
          j--;
        else if(input_str[i] == input_str[j]) {
          k++;
        }
      }
      while(j >= 0 && k < input_str.length())
        {
          if(input_str[j] != input_str[k])
            break;
          else
            {
              j--;
              k++;
            }
          isPal = input_str.substr(j + 1, k - j - 1);
            if(isPal.length() > largest.length()) {
              largest = isPal;
            }
        }
    }
  return largest;
}

2
这个代码几乎以O(n^2)的时间运行。为什么要构建一个O(n)的isPal操作来测量它的长度呢?此外,它在处理偶数回文时存在错误的尝试。关于偶数回文的错误:else if(input_str[i] == input_str[j])永远不可能成功,因为同样的测试必须在之前的if语句中失败;而且它本身就有漏洞,因为你无法仅仅通过查看相隔两个位置的2个字符来确定你是否正在查看一个偶数回文还是奇数回文(考虑AAAAAAA)。 - j_random_hacker

0

以下代码计算偶数长度和奇数长度字符串的回文。

虽然不是最佳解决方案,但适用于两种情况。

HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE

private static String getLongestPalindrome(String string) {
    String odd = getLongestPalindromeOdd(string);
    String even = getLongestPalindromeEven(string);
    return (odd.length() > even.length() ? odd : even);
}

public static String getLongestPalindromeOdd(final String input) {
    int rightIndex = 0, leftIndex = 0;
    String currentPalindrome = "", longestPalindrome = "";
    for (int centerIndex = 1; centerIndex < input.length() - 1; centerIndex++) {
        leftIndex = centerIndex;
        rightIndex = centerIndex + 1;
        while (leftIndex >= 0 && rightIndex < input.length()) {
            if (input.charAt(leftIndex) != input.charAt(rightIndex)) {
                break;
            }
            currentPalindrome = input.substring(leftIndex, rightIndex + 1);
            longestPalindrome = currentPalindrome.length() > longestPalindrome
                    .length() ? currentPalindrome : longestPalindrome;
            leftIndex--;
            rightIndex++;
        }
    }
    return longestPalindrome;
}

public static String getLongestPalindromeEven(final String input) {
    int rightIndex = 0, leftIndex = 0;
    String currentPalindrome = "", longestPalindrome = "";
    for (int centerIndex = 1; centerIndex < input.length() - 1; centerIndex++) {
        leftIndex = centerIndex - 1;
        rightIndex = centerIndex + 1;
        while (leftIndex >= 0 && rightIndex < input.length()) {
            if (input.charAt(leftIndex) != input.charAt(rightIndex)) {
                break;
            }
            currentPalindrome = input.substring(leftIndex, rightIndex + 1);
            longestPalindrome = currentPalindrome.length() > longestPalindrome
                    .length() ? currentPalindrome : longestPalindrome;
            leftIndex--;
            rightIndex++;
        }
    }
    return longestPalindrome;
}

0

这里我写了一个逻辑,试试吧 :)

public class palindromeClass{

public  static String longestPalindromeString(String in) {
        char[] input = in.toCharArray();
        int longestPalindromeStart = 0;
        int longestPalindromeEnd = 0;

        for (int mid = 0; mid < input.length; mid++) {
            // for odd palindrome case like 14341, 3 will be the mid
            int left = mid-1;
            int right = mid+1;
            // we need to move in the left and right side by 1 place till they reach the end
            while (left >= 0 && right < input.length) {
                // below check to find out if its a palindrome
                if (input[left] == input[right]) {
                    // update global indexes only if this is the longest one till now
                    if (right - left > longestPalindromeEnd
                            - longestPalindromeStart) {
                        longestPalindromeStart = left;
                        longestPalindromeEnd = right;
                    }
                }
                else
                    break;
                left--;
                right++;
            }
            // for even palindrome, we need to have similar logic with mid size 2
            // for that we will start right from one extra place
            left = mid;
            right = mid + 1;// for example 12333321 when we choose 33 as mid
            while (left >= 0 && right < input.length)
            {
                if (input[left] == input[right]) {
                    if (right - left > longestPalindromeEnd
                            - longestPalindromeStart) {
                        longestPalindromeStart = left;
                        longestPalindromeEnd = right;
                    }
                }
                else
                    break;
                left--;
                right++;
            }


        }
        // we have the start and end indexes for longest palindrome now
        return in.substring(longestPalindromeStart, longestPalindromeEnd + 1);
    }
public static void main(String args[]){
System.out.println(longestPalindromeString("HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE"));
}

}

这将返回字符串中的所有回文,而不仅仅是最长的。 - Vivek Mishra

0
  1. 修改字符串以使用分隔符分隔每个字符[这是为了包含奇数和偶数回文]
  2. 以每个字符为中心查找回文

我们可以使用此方法找到所有长度的回文。

示例:

word = abcdcbc

modifiedString = a#b#c#d#c#b#c

palinCount = 1010105010301

最长回文的长度=5;

最长回文=bcdcb

public class MyLongestPalindrome {

static String word;
static int wordlength;
static int highestcount = 0;
static int newlength;
static char[] modifiedString; // stores modified string
static int[] palinCount; // stores palindrome length at each position
static char pound = '#';

public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub
    System.out.println("Enter String : ");
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader bfr = new BufferedReader(isr);
    word = bfr.readLine();
    wordlength = word.length();
    newlength = (wordlength * 2) - 1;
    convert();
    findpalindrome();
    display();
}

// Inserting # in string
public static void convert() {

    modifiedString = new char[newlength];
    int j = 0;
    int i;
    for (i = 0; i < wordlength - 1; i++) {
        modifiedString[j++] = word.charAt(i);
        modifiedString[j++] = pound;
    }
    modifiedString[j] = word.charAt(i);
}

// display all palindromes of highest length
public static void display() {
    String palindrome;
    String s = new String(modifiedString);
    System.out.println("Length of longest palindrome = " + highestcount);
    for (int i = 0; i < newlength; i++) {
        if (palinCount[i] == highestcount) {
            palindrome = s.substring(i - (highestcount - 1), i
                    + (highestcount));
            i = i + (highestcount - 1);
            palindrome = palindrome.replace("#", "");
            System.out.println(palindrome);
        }
    }
}

// populate palinCount with length of palindrome string at each position
public static void findpalindrome() {
    int left, right, count;
    palinCount = new int[newlength];
    palinCount[0] = 1;
    palinCount[newlength - 1] = 1;
    for (int i = 1; i < newlength - 1; i++) {
        count = 0;
        left = i - 1;
        right = i + 1;
        ;
        if (modifiedString[i] != pound)
            count++;
        while (left >= 0 && right < newlength) {
            if (modifiedString[left] == modifiedString[right]) {
                if (modifiedString[left] != pound)
                    count = count + 2;
                left--;
                right++;
            } else
                break;
        }

        palinCount[i] = count;
        highestcount = count > highestcount ? count : highestcount;

    }

}

}


0

这是一个JavaScript的实现:

var longestPalindromeLength = 0;
var longestPalindrome = ''

function isThisAPalidrome(word){
  var reverse = word.split('').reverse().join('')
  return word == reverse
}

function findTheLongest(word){ // takes a word of your choice
  for(var i = 0; i < word.length; i++){ // iterates over each character
    var wordMinusOneFromBeginning = word.substr(i, word.length) // for each letter, create the word minus the first char
    for(var j = wordMinusOneFromBeginning.length; j > 0; j--){ // for the length of the word minus the first char
      var wordMinusOneFromEnding = wordMinusOneFromBeginning.substr(0, j) // create a word minus the end character
      if(wordMinusOneFromEnding <= 0) // make sure the value is more that 0,
      continue // if more than zero, proced to next if statement
      if(isThisAPalidrome(wordMinusOneFromEnding)){ // check if the word minus the first character, minus the last character = a plaindorme
        if(wordMinusOneFromEnding.length > longestPalindromeLength){ // if it is
          longestPalindromeLength = wordMinusOneFromEnding.length; // save its length
          longestPalindrome = wordMinusOneFromEnding // and save the string itself
        } // exit the statement that updates the longest palidrome
      } // exit the stament that checks for a palidrome
    } // exit the loop that goes backwards and takes a letter off the ending
  } // exit the loop that goes forward and takes off the beginning letter
  return console.log('heres the longest string: ' + longestPalindrome
  + ' its ' + longestPalindromeLength + ' charachters in length'); // return the longest palidrome! :)
}
findTheLongest('bananas');


不知道为什么这个被踩了——它的效果非常好。让我在与CA技术公司的面试中表现得很好。 - alex bennett

0

#longest palindrome
s='HYTBCABADEFGHABCDEDCBAGHTFYW123456789987654321ZWETYGDE'
out1=[]
def substring(x):
    for i in range(len(x)):
        a=x[i:]
        b=x[:-i]
        out1.append(a)
        out1.append(b)
        
    return out1

for i in range(len(s)):
    substring(s[i:])    
final=set([item for item in out1 if len(item)>2])
final
palind={item:len(item) for item in final if item==item[::-1]}
print(palind)
sorted(palind.items(),reverse=True, key=lambda x: x[1])[0]

{'DED': 3,'123456789987654321': 18,'67899876': 8,'ABCDEDCBA': 9,'456789987654': 12,'34567899876543': 14,'BCDEDCB': 7,'ABA': 3,'5678998765': 10,'2345678998765432': 16,'CDEDC': 5,'789987': 6,'8998': 4}('123456789987654321', 18)


0

对于线性解决方案,您可以使用Manacher算法。还有另一种算法称为Gusfield算法,以下是Java代码:

public class Solution {  
    char[] temp;   
    public int match(int a, int b,int len){   
        int i = 0;   
        while (a-i>=0 && b+i<len && temp[a-i] == temp[b+i]) i++;   
        return i;   
    }  

    public String longestPalindrome(String s) {  

        //This makes use of the assumption that the string has not more than 1000 characters.  
        temp=new char[1001*2];  
        int[] z=new int[1001 * 2];  
        int L=0, R=0;  
        int len=s.length();  

        for(int i=0;i<len*2+1;i++){  
            temp[i]='.';  
        }  

        for(int i=0;i<len;++i){  
            temp[i*2+1] = s.charAt(i);  
        }  

        z[0]=1;  
        len=len*2+1;  

        for(int i=0;i<len;i++){  
            int ii = L - (i - L);     
            int n = R + 1 - i;  
            if (i > R)  
            {  
                z[i] = match(i, i,len);  
                L = i;  
                R = i + z[i] - 1;  
            }  
            else if (z[ii] == n)  
            {  
                z[i] = n + match(i-n, i+n,len);  
                L = i;  
                R = i + z[i] - 1;  
            }  
            else  
            {  
                z[i] = (z[ii]<= n)? z[ii]:n;  
            }   
        }  

        int n = 0, p = 0;  
        for (int i=0; i<len; ++i)  
            if (z[i] > n)  
                n = z[p = i];  

        StringBuilder result=new StringBuilder();  
        for (int i=p-z[p]+1; i<=p+z[p]-1; ++i)  
            if(temp[i]!='.')  
                result.append(String.valueOf(temp[i]));  

        return result.toString();  
    }  
}  

您可以在我的博客中找到更多关于其他解决方案,例如最佳O(n^2)解决方案或Manacher算法。


0

编写程序从给定字符串中查找最长的回文子串。

 package source;
    
    import java.util.ArrayList;
            
    public class LongestPalindrome 
    {
        //Check the given string is palindrome by 
        public static boolean isPalindrome (String s)
        {
            StringBuffer sb = new StringBuffer(s);
            if(s.equalsIgnoreCase(sb.reverse().toString()))
                return true;
            else
                return false;
        }
    
        public static void main(String[] args) 
        {
            //String / word without space
            String str = "MOMABCMOMOM"; // "mom" //abccbabcd
            
            if(str.length() > 2 )
            {
                StringBuffer sb = new StringBuffer();
                ArrayList<String> allPalindromeList = new ArrayList<>();
                        
                for(int i=0; i<str.length(); i++)
                {
                    for(int j=i; j<str.length(); j++)
                    {
                        sb.append(str.charAt(j));
                        if( isPalindrome(sb.toString()) ) {
                            allPalindromeList.add(sb.toString());                       
                        }
                    }
                    //clear the stringBuffer
                    sb.delete(0, sb.length());
                }
                 
                int maxSubStrLength = -1;
                int indexMaxSubStr = -1;
                int index = -1;
                
                for (String subStr : allPalindromeList) {
                    ++index;
                    if(maxSubStrLength < subStr.length()) {
                        maxSubStrLength = subStr.length();
                        indexMaxSubStr = index;
                    }
                }
                if(maxSubStrLength > 2)
                    System.out.println("Maximum Length Palindrome SubString is : "+allPalindromeList.get(indexMaxSubStr));
                else
                    System.out.println("Not able to find a Palindrome who is three character in length!!");
            
            }
        }
    
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接