Viết một hàm trả về palindrome dài nhất trong một chuỗi đã cho


102

ví dụ: "ccddcc" trong chuỗi "abaccddccefe"

Tôi đã nghĩ ra một giải pháp nhưng nó chạy trong O (n ^ 2) thời gian

Algo 1:

Các bước: Đó là một phương pháp vũ phu

  1. Có 2 vòng lặp
    for cho i = 1 đến i nhỏ hơn array.length -1
    cho j = i + 1 đến j nhỏ hơn array.length
  2. Bằng cách này, bạn có thể nhận được chuỗi con của mọi kết hợp có thể có từ mảng
  3. Có một hàm palindrome kiểm tra xem một chuỗi có phải là palindrome không
  4. vì vậy đối với mọi chuỗi con (i, j) gọi hàm này, nếu nó là một palindrome thì hãy lưu trữ nó trong một biến chuỗi
  5. Nếu bạn tìm thấy chuỗi con palindrome tiếp theo và nếu nó lớn hơn chuỗi hiện tại, hãy thay thế nó bằng chuỗi hiện tại.
  6. Cuối cùng biến chuỗi của bạn sẽ có câu trả lời

Vấn đề: 1. Thuật ngữ này chạy trong thời gian O (n ^ 2).

Algo 2:

  1. Đảo ngược chuỗi và lưu trữ nó trong mảng khác nhau
  2. Bây giờ hãy tìm chuỗi con phù hợp lớn nhất giữa cả hai mảng
  3. Nhưng điều này cũng chạy trong thời gian O (n ^ 2)

Các bạn có thể nghĩ ra một thuật ngữ chạy trong thời gian tốt hơn không. Nếu có thể O (n) thời gian


42
Tôi nghĩ cách đầu tiên là O(n^2)lấy các chuỗi con * O(n)để kiểm tra xem chúng có phải là palindromes không, tổng cộng là O(n^3)?
Skylar Saveland

Điều gì sẽ xảy ra nếu tôi biết tôi đang làm việc với palindrome và lưu chuỗi của tôi thành hai nửa và sau đó nếu tôi sử dụng Java, tôi sẽ kiểm tra hàm O (1) cho hàm?
viki.omega9

10
Thuật ngữ secong là chính xác? Còn về chuỗi: "abcdecba". Chuỗi con phù hợp lớn nhất là ("abcdecba" so với "abcedcba"): "abc" hoặc "cba". Tuy nhiên, cả hai đều không phải là palindromes.
Yarneo

@Learner, chỉ tò mò, trong các bước trên, bạn đang tham chiếu đến mảng nào trong vòng lặp for của mình? Theo mảng, bạn đang đề cập đến chuỗi? chiều dài chuỗi?
Zolt

1
cho những người đang tìm kiếm câu trả lời với O (n ^ 2) - geeksforgeeks.org/longest-palindrome-substring-set-1
Shirish Herwade

Câu trả lời:


76

Bạn có thể tìm thấy palindrome dài nhất bằng cách sử dụng Thuật toán Manacher trong O(n)thời gian! Việc triển khai nó có thể được tìm thấy ở đâyở đây .

Đối với đầu vào, String s = "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE"nó sẽ tìm đầu ra chính xác 1234567887654321.


3
Tôi không hiểu điều này là tuyến tính như thế nào. tôi thấy một whilenhúng trong forvới một giới hạn có vẻ tương tự như vòng lặp bên ngoài.
v.oddou


9

Algo 2 có thể không hoạt động cho tất cả các chuỗi. Đây là một ví dụ về chuỗi như vậy "ABCDEFCBA".

Không phải là chuỗi có "ABC" và "CBA" là chuỗi con của nó. Nếu bạn đảo ngược chuỗi ban đầu, nó sẽ là "ABCFEDCBA". và chuỗi con phù hợp dài nhất là "ABC" không phải là palindrome.

Bạn có thể cần phải kiểm tra thêm xem chuỗi con phù hợp dài nhất này có thực sự là một palindrome có thời gian chạy là O (n ^ 3) hay không.


2
Điều quan trọng cần lưu ý là Algo 2 phải hoạt động cho "palindrome kết hợp con dài nhất", đây là một vấn đề thuật toán phổ biến trong đó các ký tự của dãy con cũng có thể được phân tách trong chuỗi. Ví dụ: dãy con phù hợp dài nhất (bao gồm cả phân cách ký tự) giữa hai chuỗi trên là "ABCFCBA" cũng là một palindrome :) Đây là liên kết mô tả vấn đề LCS: ics.uci.edu/~eppstein/161/960229.html
Jake Drew

5

Theo như tôi hiểu vấn đề, chúng ta có thể tìm thấy các palindromes xung quanh chỉ mục trung tâm và mở rộng tìm kiếm của chúng tôi theo cả hai cách, ở bên phải và bên trái của trung tâm. Với điều đó và biết không có palindrome ở các góc của đầu vào, chúng ta có thể đặt các ranh giới thành 1 và độ dài-1. Trong khi chú ý đến ranh giới tối thiểu và tối đa của Chuỗi, chúng tôi xác minh xem các ký tự ở vị trí của các chỉ mục đối xứng (phải và trái) có giống nhau đối với mỗi vị trí trung tâm hay không cho đến khi chúng tôi đạt đến trung tâm giới hạn trên tối đa.

Vòng lặp bên ngoài là O (n) (tối đa n-2 lần lặp) và vòng lặp while bên trong là O (n) (tối đa khoảng (n / 2) - 1 lần lặp)

Đây là cách triển khai Java của tôi bằng cách sử dụng ví dụ do người dùng khác cung cấp.

class LongestPalindrome {

    /**
     * @param input is a String input
     * @return The longest palindrome found in the given input.
     */
    public static String getLongestPalindrome(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;
    }

    public static void main(String ... args) {
        String str = "HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE";
        String longestPali = getLongestPalindrome(str);
        System.out.println("String: " + str);
        System.out.println("Longest Palindrome: " + longestPali);
    }
}

Kết quả của điều này là như sau:

marcello:datastructures marcello$ javac LongestPalindrome
marcello:datastructures marcello$ java LongestPalindrome
String: HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE
Longest Palindrome: 12345678987654321

6
Nếu tôi cung cấp "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE" Nó không hoạt động Nhưng anwer phải là 1234567887654321
Elbek

1
@j_random_hacker nope, đó là một trong những giải pháp bậc hai. Nó được bảo hiểm ở đây như expandAroundCenter.
v.oddou,

@ v.oddou: Bạn hoàn toàn đúng, và tôi không biết làm thế nào tôi kết luận O (n ^ 3) vì chỉ có 2 vòng lặp lồng nhau! Tôi sẽ xóa bình luận nhầm lẫn đó ... Nhưng tôi cũng nhận thấy rằng giải pháp này có vấn đề, tôi sẽ đưa ra một bình luận riêng để tác giả hy vọng thông báo.
j_random_hacker

Tuyên bố trước đó của tôi về độ phức tạp thời gian O (n ^ 3) là sai (cảm ơn @ v.oddou đã chỉ ra điều này!) Nhưng có một vấn đề khác: mã này không xem xét các palindrom có ​​độ dài chẵn. Điều này có thể được khắc phục bằng cách thêm một vòng lặp thứ hai, rất tương tự bên ngoài (cũng là O (n ^ 2) để nó không ảnh hưởng đến độ phức tạp thời gian O (n ^ 2)) mở rộng các palindromes xung quanh mỗi vị trí trong số n-1 giữa mỗi cặp ký tự. 2 nếu bạn khắc phục :)
j_random_hacker

2

với regex và ruby, bạn có thể quét các palindromes ngắn như sau:

PROMPT> irb
>> s = "longtextwithranynarpalindrome"
=> "longtextwithranynarpalindrome"
>> s =~ /((\w)(\w)(\w)(\w)(\w)\6\5\4\3\2)/; p $1
nil
=> nil
>> s =~ /((\w)(\w)(\w)(\w)\w\5\4\3\2)/; p $1
nil
=> nil
>> s =~ /((\w)(\w)(\w)(\w)\5\4\3\2)/; p $1
nil
=> nil
>> s =~ /((\w)(\w)(\w)\w\4\3\2)/; p $1
"ranynar"
=> nil

2

Tôi đã viết chương trình Java sau vì tò mò, HTH đơn giản và dễ hiểu. Cảm ơn.

/**
 *
 * @author sanhn
 */
public class CheckPalindrome {

    private static String max_string = "";

    public static void checkSubString(String s){
        System.out.println("Got string is "+s);
        for(int i=1;i<=s.length();i++){
            StringBuilder s1 = new StringBuilder(s.substring(0,i));
            StringBuilder s2 = new StringBuilder(s.substring(0,i));
            s2.reverse();
            if(s1.toString().equals(s2.toString())){
                if(max_string.length()<=s1.length()){
                    max_string = s1.toString();
                    System.out.println("tmp max is "+max_string);
                }

            }
        }
    }

    public static void main(String[] args){
        String s="HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE";

        for(int i=0; i<s.length(); i++)
            checkSubString(s.substring(i, s.length()));

        System.out.println("Max string is "+max_string);
    }
}

1

Tôi đã được hỏi câu hỏi này gần đây. Đây là giải pháp mà tôi [cuối cùng] đã đưa ra. Tôi đã làm điều đó bằng JavaScript vì nó khá đơn giản trong ngôn ngữ đó.

Khái niệm cơ bản là bạn đi chuỗi tìm kiếm palindrome nhiều ký tự nhỏ nhất có thể (một hai hoặc ba ký tự). Khi bạn đã có điều đó, hãy mở rộng đường viền ở cả hai bên cho đến khi nó không còn là palindrome nữa. Nếu độ dài đó dài hơn độ dài hiện tại, hãy cất nó và di chuyển.

// This does the expanding bit.
function getsize(s, start, end) {
    var count = 0, i, j;
    for (i = start, j = end; i >= 0 && j < s.length; i--, j++) {
        if (s[i] !== s[j]) {
            return count;
        }
        count = j - i + 1; // keeps track of how big the palindrome is
    }
    return count;
}

function getBiggestPalindrome(s) {
    // test for simple cases
    if (s === null || s === '') { return 0; }
    if (s.length === 1) { return 1; }
    var longest = 1;
    for (var i = 0; i < s.length - 1; i++) {
        var c = s[i]; // the current letter
        var l; // length of the palindrome
        if (s[i] === s[i+1]) { // this is a 2 letter palindrome
            l = getsize(s, i, i+1);
        }
        if (i+2 < s.length && s[i] === s[i+2]) { // 3 letter palindrome
            l = getsize(s, i+1, i+1);
        }
        if (l > longest) { longest = l; }
    }
    return longest;
}

Điều này chắc chắn có thể được dọn dẹp và tối ưu hóa nhiều hơn một chút, nhưng nó sẽ có hiệu suất khá tốt trong tất cả trừ trường hợp xấu nhất (một chuỗi ký tự giống nhau).


1
Tôi ban đầu nghĩ rằng thuật toán số 1 của OP là thời gian O (n ^ 2), nhưng thực tế nó là O (n ^ 3), vì vậy, mặc dù thuật toán của bạn không hoàn thành đến giới hạn O (n) có thể đạt được, nó vẫn là một cải tiến.
j_random_hacker

1
bạn gọi điều này là "đơn giản" nhưng nó đầy đủ i j l s ifvà bảo trì trạng thái. điểm trở lại đa, trường hợp cạnh ...
v.oddou

1

Xin chào Đây là mã của tôi để tìm palindrome dài nhất trong chuỗi. Vui lòng tham khảo liên kết sau để hiểu thuật toán http://stevekrenzel.com/articles/longest-palnidrome

Dữ liệu kiểm tra được sử dụng là HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE

 //Function GetPalindromeString

public static string GetPalindromeString(string theInputString)
 { 

        int j = 0;
        int k = 0;
        string aPalindrome = string.Empty;
        string aLongestPalindrome = string.Empty ;          
        for (int i = 1; i < theInputString.Length; i++)
        {
            k = i + 1;
            j = i - 1;
            while (j >= 0 && k < theInputString.Length)
            {
                if (theInputString[j] != theInputString[k])
                {
                    break;
                }
                else
                {
                    j--;
                    k++;
                }
                aPalindrome = theInputString.Substring(j + 1, k - j - 1);
                if (aPalindrome.Length > aLongestPalindrome.Length)
                {
                    aLongestPalindrome = aPalindrome;
                }
            }
        }
        return aLongestPalindrome;     
  }

Tôi không chắc liệu điều này có hiệu quả với các palindromes có độ dài đồng đều hay không ... bạn có thể xác nhận?
st0le

Công trình này cho palindromes thậm chí bạn có thể chạy chương trình này và cho tôi biết nếu không được làm việc cho sự hiểu biết you.For của thuật toán vui lòng tham khảo liên kết sau stevekrenzel.com/articles/longest-palnidrome
Mohit Bhandari

@ st0le: Logic này sẽ không hoạt động đối với thậm chí palindromes nhưng nó có thể được điều chỉnh cho thậm chí palindromes. Tôi xin lỗi vì sự thông thường sớm hơn. Tôi có logic này và tôi sẽ cập nhật nó trong vài ngày tới và khi tôi có thời gian.
Mohit Bhandari

không bao giờ đọc bình luận trước đây của bạn cho đến ngày hôm nay ... bạn đã không nói với tôi lần trước .... hãy dành thời gian của bạn, nó chỉ là một quan sát.
st0le

2
Tôi ban đầu nghĩ rằng thuật toán số 1 của OP là thời gian O (n ^ 2), nhưng thực tế nó là O (n ^ 3), vì vậy, mặc dù thuật toán của bạn không hoàn thành đến giới hạn O (n) có thể đạt được, nó vẫn là một cải tiến.
j_random_hacker

1

Xem bài viết trên Wikipedia về chủ đề này. Mẫu triển khai Java thuật toán của Manacher cho giải pháp O (n) tuyến tính từ bài viết dưới đây:

nhập java.util.Arrays; public class ManachersAlgorithm {public static String findLongestPalindrome (String s) {if (s == null || s.length () == 0) return "";

char[] s2 = addBoundaries(s.toCharArray());
int[] p = new int[s2.length]; 
int c = 0, r = 0; // Here the first element in s2 has been processed.
int m = 0, n = 0; // The walking indices to compare if two elements are the same
for (int i = 1; i<s2.length; i++) {
  if (i>r) {
    p[i] = 0; m = i-1; n = i+1;
  } else {
    int i2 = c*2-i;
    if (p[i2]<(r-i)) {
      p[i] = p[i2];
      m = -1; // This signals bypassing the while loop below. 
    } else {
      p[i] = r-i;
      n = r+1; m = i*2-n;
    }
  }
  while (m>=0 && n<s2.length && s2[m]==s2[n]) {
    p[i]++; m--; n++;
  }
  if ((i+p[i])>r) {
    c = i; r = i+p[i];
  }
}
int len = 0; c = 0;
for (int i = 1; i<s2.length; i++) {
  if (len<p[i]) {
    len = p[i]; c = i;
  }
}
char[] ss = Arrays.copyOfRange(s2, c-len, c+len+1);
return String.valueOf(removeBoundaries(ss));   }
private static char[] addBoundaries(char[] cs) {
if (cs==null || cs.length==0)
  return "||".toCharArray();

char[] cs2 = new char[cs.length*2+1];
for (int i = 0; i<(cs2.length-1); i = i+2) {
  cs2[i] = '|';
  cs2[i+1] = cs[i/2];
}
cs2[cs2.length-1] = '|';
return cs2;   }
private static char[] removeBoundaries(char[] cs) {
if (cs==null || cs.length<3)
  return "".toCharArray();

char[] cs2 = new char[(cs.length-1)/2];
for (int i = 0; i<cs2.length; i++) {
  cs2[i] = cs[i*2+1];
}
return cs2;   }     }

1

Một Regexpgiải pháp hiệu quả tránh bạo lực

Bắt đầu với toàn bộ độ dài chuỗi và kéo dài xuống 2 ký tự, tồn tại ngay sau khi khớp được thực hiện

Đối với "abaccddccefe"các bài kiểm tra regexp 7 trận đấu trước khi trở lại ccddcc.

(.) (.) (.) (.) (.) (.) (\ 6) (\ 5) (\ 4) (\ 3) (\ 2) (\ 1)
(.) (.) (.) (.) ) (.) (.) (.) (\ 5) (\ 4) (\ 3) (\ 2) (\ 1)
(.) (.) (.) (.) (.) (\ 5) ( \ 4) (\ 3) (\ 2) (\ 1)
(.) (.) (.) (.) (.) (\ 4) (\ 3) (\ 2) (\ 1)
(.) ( .) (.) (.) (\ 4) (\ 3) (\ 2) (\ 1)
(.) (.) (.) (.) (\ 3) (\ 2) (\ 1)
(. ) (.) (.) (\ 3) (\ 2) (\ 1)

Dim strTest
wscript.echo Palindrome("abaccddccefe")

Sub Test()
Dim strTest
MsgBox Palindrome("abaccddccefe")
End Sub

chức năng

Function Palindrome(strIn)

Set objRegex = CreateObject("vbscript.regexp")

For lngCnt1 = Len(strIn) To 2 Step -1
    lngCnt = lngCnt1 \ 2
    strPal = vbNullString

    For lngCnt2 = lngCnt To 1 Step -1
        strPal = strPal & "(\" & lngCnt2 & ")"
    Next

    If lngCnt1 Mod 2 = 1 Then strPal = "(.)" & strPal

    With objRegex
        .Pattern = Replace(Space(lngCnt), Chr(32), "(.)") & strPal
        If .Test(strIn) Then
            Palindrome = .Execute(strIn)(0)
            Exit For
        End If
    End With
Next

End Function

@DickKusleika bạn có thể cập nhật nhận xét của tôi tại dailydoseofexcel.com/archives/2016/01/14/… với mã sửa đổi ở trên không. Thx
brettdj

1
public static void main(String[] args) {
         System.out.println(longestPalindromeString("9912333321456")); 
}

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


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

0

Hãy thử chuỗi - "HYTBCABADEFGHABCDEDCBAGHTFYW123456789987654321ZWETYGDE"; Nó sẽ hoạt động cho những người bạn chẵn và lẻ. Cảm ơn Mohit rất nhiều!

sử dụng không gian tên 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
Điều này gần như thực hiện mọi thứ trong thời gian O (n ^ 2). Tại sao phải xây dựng isPal- một phép toán O (n) - chỉ để đo chiều dài của nó !? Ngoài ra, nó còn có một lỗi trong việc xử lý thậm chí cả palindromes. Đối với bugginess chẵn-palindrome: else if(input_str[i] == input_str[j])không bao giờ có thể thành công vì cùng một bài kiểm tra đó chắc chắn đã thất bại trong iftuyên bố trước đó ; và nó vẫn có lỗi vì bạn không thể biết chỉ bằng cách nhìn vào 2 ký tự cách nhau 2 vị trí cho dù bạn đang xem palindrome chẵn hay lẻ (hãy xem xét AAAAAAA).
j_random_hacker

0

Đoạn mã sau sẽ tính toán Palidrom cho các chuỗi có độ dài chẵn và độ dài lẻ.

Không phải là giải pháp tốt nhất nhưng hiệu quả cho cả hai trường hợp

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
  1. Sửa đổi chuỗi để phân tách từng ký tự bằng dấu phân tách [điều này là để kết hợp các palindromes lẻ và chẵn]
  2. Tìm các palindromes xung quanh mỗi nhân vật coi đó là trung tâm

Chúng tôi có thể tìm thấy tất cả các palindromes ở mọi độ dài bằng cách sử dụng điều này.

Mẫu vật :

word = abcdcbc

modString = a # b # c # d # c # b # c

palinCount = 1010105010301

chiều dài của palindrome dài nhất = 5;

palindrome dài nhất = bcdcb

lớp công khai 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

Điều này sẽ trả về chuỗi palindrome dài nhất từ ​​chuỗi đã cho

-(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"];
}

== ĐẦU RA ===

Đầu vào: abcccde Đầu ra: ccc

Đầu vào: abcccbd Đầu ra: bcccb

Đầu vào: abedccde Đầu ra: edccde

Đầu vào: abcccdeed Đầu ra: chứng thư

Đầu vào: abcccbadeed Đầu ra: abcccba


0

Đây là một triển khai trong 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');


Không biết tại sao điều này lại bị bỏ phiếu - hoạt động như một sự quyến rũ. Giúp tôi có một cuộc phỏng vấn với các công nghệ CA tốt.
alex bennett

0

Đối với giải pháp tuyến tính, bạn có thể sử dụng thuật toán Manacher. Có một thuật toán khác được gọi là Thuật toán của Gusfield và dưới đây là mã trong 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();  
    }  
}  

Bạn có thể tìm thêm về các giải pháp khác như giải pháp O (n ^ 2) tốt nhất hoặc thuật toán Manacher từ blog của riêng tôi .


0

Ở đây tôi đã viết một logic, hãy thử nó :)

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

}

này cung cấp cho tất cả các palindrome trong chuỗi không chỉ là dài nhất
Vivek Mishra

0

Giải pháp này có độ phức tạp O (n ^ 2). O (1) là độ phức tạp của không gian.

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

#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)


-1

Đây là thuật toán của tôi:

1) đặt tâm hiện tại là chữ cái đầu tiên

2) đồng thời mở rộng sang trái và phải cho đến khi bạn tìm thấy palindrome cực đại xung quanh tâm hiện tại

3) nếu palindrome bạn tìm thấy lớn hơn palindrome trước đó, hãy cập nhật nó

4) đặt tâm hiện tại là chữ cái tiếp theo

5) lặp lại bước 2) đến 4) cho tất cả các chữ cái trong chuỗi

Điều này chạy trong O (n).

Hy vọng nó giúp.


5
Xét chuỗi "aaaaaa". Điều này chạy trong O (n ^ 2) bằng cách sử dụng thuật toán của bạn.
paislee

1
Tôi ban đầu nghĩ rằng thuật toán số 1 của OP là thời gian O (n ^ 2), nhưng thực tế nó là O (n ^ 3), vì vậy, mặc dù thuật toán của bạn không hoàn thành đến giới hạn O (n) có thể đạt được, nó vẫn là một cải tiến.
j_random_hacker

Đó là giải pháp mở rộng N2 cổ điển. NHƯNG, Trên thực tế, đó là giải pháp của Manacher như được giải thích trong video này: youtube.com/watch?v=V-sEwsca1ak, điểm khác biệt là điểm 4. Người quản lý sử dụng lại thông tin để có thể tránh quét lại các chữ cái đã được quét.
v.oddou,

-2

Tham khảo: Wikipedia.com

Thuật toán tốt nhất mà tôi từng tìm thấy, với độ phức tạp O (N)

 import java.util.Arrays;

 public class ManachersAlgorithm {

  public static String findLongestPalindrome(String s) {
    if (s==null || s.length()==0)
      return "";

    char[] s2 = addBoundaries(s.toCharArray());
    int[] p = new int[s2.length]; 
    int c = 0, r = 0; // Here the first element in s2 has been processed.
    int m = 0, n = 0; // The walking indices to compare if two elements are the same
    for (int i = 1; i<s2.length; i++) {
      if (i>r) {
        p[i] = 0; m = i-1; n = i+1;
      } else {
        int i2 = c*2-i;
        if (p[i2]<(r-i)) {
          p[i] = p[i2];
          m = -1; // This signals bypassing the while loop below. 
        } else {
          p[i] = r-i;
          n = r+1; m = i*2-n;
        }
      }
      while (m>=0 && n<s2.length && s2[m]==s2[n]) {
        p[i]++; m--; n++;
      }
      if ((i+p[i])>r) {
        c = i; r = i+p[i];
      }
    }
    int len = 0; c = 0;
    for (int i = 1; i<s2.length; i++) {
      if (len<p[i]) {
        len = p[i]; c = i;
      }
    }
    char[] ss = Arrays.copyOfRange(s2, c-len, c+len+1);
    return String.valueOf(removeBoundaries(ss));
  }

  private static char[] addBoundaries(char[] cs) {
    if (cs==null || cs.length==0)
      return "||".toCharArray();

    char[] cs2 = new char[cs.length*2+1];
    for (int i = 0; i<(cs2.length-1); i = i+2) {
      cs2[i] = '|';
      cs2[i+1] = cs[i/2];
    }
    cs2[cs2.length-1] = '|';
    return cs2;
  }

  private static char[] removeBoundaries(char[] cs) {
    if (cs==null || cs.length<3)
      return "".toCharArray();

    char[] cs2 = new char[(cs.length-1)/2];
    for (int i = 0; i<cs2.length; i++) {
      cs2[i] = cs[i*2+1];
    }
    return cs2;
  }    
}

-5

giải pháp của tôi là:

static string GetPolyndrom(string str)
{
    string Longest = "";

    for (int i = 0; i < str.Length; i++)
    {
        if ((str.Length - 1 - i) < Longest.Length)
        {
            break;
        }
        for (int j = str.Length - 1; j > i; j--)
        {
            string str2 = str.Substring(i, j - i + 1);
            if (str2.Length > Longest.Length)
            {
                if (str2 == str2.Reverse())
                {
                    Longest = str2;
                }
            }
            else
            {
                break;
            }
        }

    }
    return Longest;
}

1
Điều này mất thời gian khối đối với độ dài chuỗi, do các phép toán Substring()và string-Equity ( ==). Về cơ bản nó giống với bí danh số 1 của OP.
j_random_hacker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.