找到最长的回文子串

Posted

技术标签:

【中文标题】找到最长的回文子串【英文标题】:Find the longest pallindrome substring 【发布时间】:2015-08-04 06:51:21 【问题描述】:

给定一个字符串,找出最长的回文子串。例如,如果给定的字符串是“forgeeksskeegfor”,则输出应该是“geeksskeeg”。

我是怎么做的? 我只知道如何找到回文即

给定一个字符串。我从 0 和长度-1 开始获取 2 个索引 i,j。比较给定索引处存在的两个字符直到 i

这是我的代码

 class StringPallendrome 

 static int length = 0;
 static int Count=0;
 static boolean stringpallendrome(String p) 
 

    boolean flag=false;
    boolean s3 = true;
    boolean s4 = false;
    char ch[] = p.toCharArray();
    for(int i=0,j=ch.length-1;i<j;i++,j--) 
       
       if(ch[i]==ch[j])
        
          flag=true;
          length++;
        
       else
       
          flag=false;
          break;
       
      
      if(flag==true)
      
            System.out.println("Its a pallendrome");
            return s3;

      
      else
      

          return s4;
      
 

public static void main(String s[]) 
 
    boolean s2;
    String a = new String("abac");
    s2 = stringpallendrome(a);
    System.out.println(s2);
 

我在各个网站上搜索了这个问题,发现它们很有用但无法理解。

http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-i.html

我解决这个问题的领域是 java 中的代码,具有简单的蛮力解决方案,然后使用没有额外空间的 o(n2) 方法,就像现在一样。 http://www.geeksforgeeks.org/longest-palindromic-substring-set-2/

【问题讨论】:

这是你的代码;你有什么问题? 那么,您的问题是什么?这是一个很常见的问题。在此处发布问题之前先进行研究。查看此链接,例如programcreek.com/2013/12/… 所以你想知道的东西是否在一个单词中有一个回文,即使它不是完整的句子,对吧? @Micho 很抱歉给您带来不便。我编辑了代码。 @Skizo 是的,而且时间太长了。 【参考方案1】:

这是一个多余的问题。你可以在这里找到答案。 Write a function that returns the longest palindrome in a given string

答案是

您可以使用 Manacher 算法在 准时!它的实现可以在here 和here 找到。 对于输入字符串 s = “HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE”。它发现 正确的输出是 1234567887654321。

【讨论】:

是的,问题是多余的。我没有要求 O(n) 中的任何 Manacher 算法。我只对了解 bruteForce 解决方案以及 O(n2) 方法感兴趣,没有额外的空间.前者我从多余的问题中理解,但后者仍然不理解。我在我的问题中提供了一个链接,来自我在 java 中理解的地方。【参考方案2】:

见Manacher's algorithm.

它的时间复杂度是O(n)。

【讨论】:

这是 manacher 的,而不是 manchester 的。尊重发明者!!【参考方案3】:

首先,检查一个字符串是否是回文可以通过:

static boolean isPalindrome(String p) 
    return p.equals(new StringBuilder(p).reverse().toString());

您的问题应该是:“如何有效地找到最长的回文?”。通常它是使用 Manacher 算法完成的。 Robert Sedgewick 和 Kevin Wayne 编写了很好的实现:

/******************************************************************************
 *  Compilation:  javac Manacher.java
 *  Execution:    java Manacher text
 *  Dependencies: StdOut.java
 *
 *  Computes the longest palindromic substring in linear time
 *  using Manacher's algorithm.
 *
 *  Credits: The code is lifted from the following excellent reference
 *  http://www.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html
 *
 ******************************************************************************/

public class Manacher 
    private int[]  p;  // p[i] = length of longest palindromic substring of t, centered at i
    private String s;  // original string
    private char[] t;  // transformed string

    public Manacher(String s) 
        this.s = s;
        preprocess();
        p = new int[t.length];

        int center = 0, right = 0;
        for (int i = 1; i < t.length-1; i++) 
            int mirror = 2*center - i;

            if (right > i)
                p[i] = Math.min(right - i, p[mirror]);

            // attempt to expand palindrome centered at i
            while (t[i + (1 + p[i])] == t[i - (1 + p[i])])
                p[i]++;

            // if palindrome centered at i expands past right,
            // adjust center based on expanded palindrome.
            if (i + p[i] > right) 
                center = i;
                right = i + p[i];
            
        

    

    // Transform s into t.
    // For example, if s = "abba", then t = "$#a#b#b#a#@"
    // the # are interleaved to avoid even/odd-length palindromes uniformly
    // $ and @ are prepended and appended to each end to avoid bounds checking
    private void preprocess() 
        t = new char[s.length()*2 + 3];
        t[0] = '$';
        t[s.length()*2 + 2] = '@';
        for (int i = 0; i < s.length(); i++) 
            t[2*i + 1] = '#';
            t[2*i + 2] = s.charAt(i);
        
        t[s.length()*2 + 1] = '#';
    

    // longest palindromic substring
    public String longestPalindromicSubstring() 
        int length = 0;   // length of longest palindromic substring
        int center = 0;   // center of longest palindromic substring
        for (int i = 1; i < p.length-1; i++) 
            if (p[i] > length) 
                length = p[i];
                center = i;
            
        
        return s.substring((center - 1 - length) / 2, (center - 1 + length) / 2);
    

    // longest palindromic substring centered at index i/2
    public String longestPalindromicSubstring(int i) 
        int length = p[i + 2];
        int center = i + 2;
        return s.substring((center - 1 - length) / 2, (center - 1 + length) / 2);
    



    // test client
    public static void main(String[] args) 
        String s = args[0];
        Manacher manacher = new Manacher(s);
        StdOut.println(manacher.longestPalindromicSubstring());
        for (int i = 0; i < 2*s.length(); i++)
            StdOut.println(i +  ": " + manacher.longestPalindromicSubstring(i));

    

来源:http://algs4.cs.princeton.edu/53substring/Manacher.java.html

【讨论】:

【参考方案4】:

这是一个查找最长“偶数”长度回文的伪代码示例,您可以为最长奇数长度的回文编写非常相似的代码。

enum State = INCREMENT, EXPAND, RESET  // different states of the algorithm

int longestEvenPalindrome(String s)
    int p1 = 0, p2 = 1, p3 = 1, longestPalindrome = 1;
    State state = INCREMENT;

    while(p2 < s.length)
        switch(state)
            case INCREMENT:                    // Incr. until matching chars
                if(s[p1] == s[p2])
                    state = EXPAND;
                    p3 = p2 + 1;
                 else 
                    p1++;
                    p2++;
                
                break;

            case EXPAND:                      // Expand until mismatching chars
                if(p1 < 0 || s[p1] != s[p2])
                    state = RESET;
                 else 
                    p1--; // Expand Left
                    p2++; // Expand Right
                
                break;

            case RESET:
                longestPalindrome = Math.max(longestPalindrome, p2 - p1 - 2);
                p2 = p3;
                p1 = p3 - 1;
                state = INCREMENT;
                break;
        
    

    return longestPalindrome;

【讨论】:

【参考方案5】:
class LongPal

    public static void main (String args[])
    
        String k = new String("abcertmadamelkokokp"); //random string 
        boolean flag = false; //flag to check whether isPalindrome is true
        int i, j , max_pal =0; //max_pal keeps account of length of the longest palindrome
        String s =""; 
        String s1 = ""; //two strings

        LongPal obj = new LongPal();

        for (i=0;i<k.length();i++) //outer loop starts from index 0 of the string
        
            for (j=k.length();j>i+1;j--) //inner loop starts from the end of the string
            


                flag = obj.isPalindrome(k.substring(i,j)); //sending the substring to isPalindrome
                if (flag)
                

                    s= k.substring(i,j); //storing the palindrome  substring in s

                        if(s.length()>max_pal) // if the palindrome encountered has a length more than the previously encountered palindrome
                        
                         max_pal = s.length(); //set max_pal to the length of the new palindrome
                         s1 = s; //store the new palindrome in s1
                        

                       


            
        


        System.out.println("Longest Palindrome:  "+ s1); //print the longest palindrome

    



    public boolean isPalindrome(String s)
    
        StringBuffer s1 = new StringBuffer(s); //copy String s to StringBuffer s1
        StringBuffer s2 = new StringBuffer(s);//copy String s to StringBuffer s2

    String rev=s2.reverse().toString(); //reverse s2 and convert it into string type and store the same in rev

         if (s1.toString().equals(rev)) //convert s1 to string and compare with rev. You can't use .equals() for StringBuffer type. 

           

             return true;
         
         else
         

             return false;
         
    




【讨论】:

你能评论你的答案吗? @MartinPrikryl 做到了。 :)

以上是关于找到最长的回文子串的主要内容,如果未能解决你的问题,请参考以下文章

最长回文子串

算法提升——中心扩散法(最长回文子串和回文子串)

最长回文子串--动态规划

Leetcode最长回文子串

[LeetCode] 最长回文子串

LeetCode-005-最长回文子串