เขียนฟังก์ชันที่ส่งคืน palindrome ที่ยาวที่สุดในสตริงที่กำหนด


102

เช่น "ccddcc" ในสตริง "abaccddccefe"

ฉันคิดวิธีแก้ปัญหา แต่มันทำงานในเวลา O (n ^ 2)

อัลโก 1:

ขั้นตอน: มันเป็นวิธีการบังคับที่ดุร้าย

  1. มี 2 ​​สำหรับลูป
    สำหรับ i = 1 ถึง i น้อยกว่า array.length -1
    สำหรับ j = i + 1 ถึง j น้อยกว่า array.length
  2. ด้วยวิธีนี้คุณจะได้รับสตริงย่อยของชุดค่าผสมที่เป็นไปได้ทั้งหมดจากอาร์เรย์
  3. มีฟังก์ชัน palindrome ซึ่งตรวจสอบว่าสตริงเป็น palindrome หรือไม่
  4. ดังนั้นสำหรับทุกสตริงย่อย (i, j) เรียกใช้ฟังก์ชันนี้หากเป็นพาลินโดรมเก็บไว้ในตัวแปรสตริง
  5. หากคุณพบสตริงย่อยของพาลินโดรมถัดไปและหากมีค่ามากกว่าสตริงปัจจุบันให้แทนที่ด้วยสตริงปัจจุบัน
  6. ในที่สุดตัวแปรสตริงของคุณจะมีคำตอบ

ประเด็น: 1. อัลโกนี้ทำงานในเวลา O (n ^ 2)

อัลโก 2:

  1. ย้อนกลับสตริงและเก็บไว้ในอาร์เรย์ที่แตกต่างกัน
  2. ตอนนี้ค้นหาสตริงย่อยที่ตรงกันที่ใหญ่ที่สุดระหว่างอาร์เรย์ทั้งสอง
  3. แต่สิ่งนี้ก็ทำงานในเวลา O (n ^ 2) เช่นกัน

พวกคุณนึกถึงอัลโกที่วิ่งในเวลาที่ดีกว่าได้ไหม ถ้าเป็นไปได้ O (n) เวลา


42
ฉันคิดว่าสิ่งแรกคือO(n^2)การรับสตริงย่อย * O(n)เพื่อตรวจสอบว่าเป็น palindromes O(n^3)หรือไม่โดยรวม
Skylar Saveland

จะเกิดอะไรขึ้นถ้าฉันรู้ว่าฉันกำลังทำงานกับ palindrome และบันทึกสตริงของฉันเป็นสองซีกแล้วถ้าฉันใช้ Java ฉันจะมี O (1) ตรวจสอบฟังก์ชัน
viki.omega9

10
secong algo ถูกต้องหรือไม่? สิ่งที่เกี่ยวกับสตริง: "abcdecba" สตริงย่อยที่ตรงกันมากที่สุดคือ ("abcdecba" เทียบกับ "abcedcba"): "abc" หรือ "cba" อย่างไรก็ตามทั้งสองไม่ใช่ palindromes
Yarneo

@ เรียนรู้เพียงแค่อยากรู้อยากเห็นในขั้นตอนเหนืออาร์เรย์ใดที่คุณกำลังตัดสินในลูปของคุณ? โดยอาร์เรย์คุณหมายถึงสตริงหรือไม่? string.length?
Zolt

1
สำหรับผู้ที่ค้นหาคำตอบด้วย O (n ^ 2) - geeksforgeeks.org/longest-palindrome-substring-set-1
Shirish Herwade

คำตอบ:


76

คุณสามารถค้นหาพาลินโดรมที่ยาวที่สุดได้โดยใช้อัลกอริทึมของ ManacherในO(n)เวลา! การดำเนินงานที่สามารถพบได้ที่นี่และที่นี่

สำหรับอินพุตString s = "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE"จะค้นหาเอาต์พุตที่ถูกต้องซึ่งเป็น1234567887654321ที่พบการส่งออกที่ถูกต้องซึ่งเป็น


3
ฉันไม่เข้าใจว่ามันเป็นเส้นตรงได้อย่างไร ฉันเห็นสิ่งที่whileฝังอยู่ในforขอบเขตที่ดูเหมือนกับวงนอก
v.oddou


9

Algo 2 อาจใช้ไม่ได้กับสตริงทั้งหมด นี่คือตัวอย่างของสตริง "ABCDEFCBA"

ไม่ใช่ว่าสตริงมี "ABC" และ "CBA" เป็นสตริงย่อย หากคุณย้อนกลับสตริงเดิมจะเป็น "ABCFEDCBA" และสตริงย่อยที่ตรงกันที่ยาวที่สุดคือ "ABC" ซึ่งไม่ใช่พาลินโดรม

คุณอาจต้องตรวจสอบเพิ่มเติมว่าสตริงย่อยที่ตรงกันที่ยาวที่สุดนี้เป็นพาลินโดรมที่มีเวลาทำงานเป็น O (n ^ 3) หรือไม่


2
สิ่งสำคัญคือต้องทราบว่า Algo 2 ควรใช้กับ "palindrome ลำดับต่อมาที่ตรงกันที่ยาวที่สุด" ซึ่งเป็นปัญหาของอัลกอริทึมทั่วไปที่สามารถแยกอักขระลำดับต่อมาภายในสตริงได้ ตัวอย่างเช่นลำดับการจับคู่ที่ยาวที่สุด (รวมถึงการแยกอักขระ) ระหว่างสองสตริงด้านบนคือ "ABCFCBA" ซึ่งเป็น palindrome ด้วย :) นี่คือลิงค์ที่อธิบายปัญหา LCS: ics.uci.edu/~eppstein/161/960229.html
Jake Drew

5

เท่าที่ฉันเข้าใจปัญหาเราสามารถค้นหา palindromes รอบ ๆ ดัชนีกลางและขยายการค้นหาของเราทั้งสองทางไปทางขวาและซ้ายของจุดศูนย์กลาง เมื่อพิจารณาจากนั้นและรู้ว่าไม่มีพาลินโดรมที่มุมของอินพุตเราสามารถกำหนดขอบเขตเป็น 1 และความยาว -1 ได้ ในขณะที่ให้ความสนใจกับขอบเขตขั้นต่ำและสูงสุดของ String เราจะตรวจสอบว่าอักขระที่ตำแหน่งของดัชนีสมมาตร (ขวาและซ้าย) เหมือนกันสำหรับแต่ละตำแหน่งกลางหรือไม่จนกว่าเราจะไปถึงจุดกึ่งกลางขอบเขตสูงสุดของเรา

วงนอกคือ O (n) (การวนซ้ำสูงสุด n-2) และวงในขณะที่ลูปคือ O (n) (รอบสูงสุด (n / 2) - การวนซ้ำ 1 ครั้ง)

นี่คือการใช้งาน Java ของฉันโดยใช้ตัวอย่างที่ผู้ใช้รายอื่นให้มา

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

ผลลัพธ์ของสิ่งนี้มีดังต่อไปนี้:

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

6
ถ้าฉันให้ "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE" มันไม่ได้ผล แต่ anwer ควรเป็น 1234567887654321
Elbek

1
@j_random_hacker ไม่นั่นคือหนึ่งในวิธีแก้ปัญหากำลังสอง ครอบคลุมที่นี่เป็นexpandAroundCenter.
v.oddou

@ v.oddou: คุณพูดถูกจริงๆและฉันไม่รู้ว่าฉันสรุป O (n ^ 3) ได้อย่างไรเนื่องจากมีลูปซ้อนกันเพียง 2 ลูป! ฉันจะลบความคิดเห็นที่ผิดพลาดนั้น ... แต่ฉันสังเกตด้วยว่าวิธีนี้มีปัญหาซึ่งฉันจะใส่ความคิดเห็นแยกต่างหากเพื่อให้ผู้เขียนสังเกตเห็น
j_random_hacker

การอ้างสิทธิ์ความซับซ้อนของเวลา O (n ^ 3) ก่อนหน้านี้ไม่ถูกต้อง (ขอบคุณ @ v.oddou ที่ชี้ให้เห็น!) แต่มีปัญหาอีกประการหนึ่งคือรหัสนี้ไม่ได้พิจารณาถึงความซับซ้อนของเวลาที่เท่ากัน สิ่งนี้สามารถแก้ไขได้โดยการเพิ่มวงรอบนอกที่สองที่คล้ายกันมาก (เช่น O (n ^ 2) ดังนั้นจึงไม่ส่งผลต่อความซับซ้อนของเวลา O (n ^ 2)) ที่ขยาย palindromes รอบ ๆ ตำแหน่ง n-1 ระหว่างแต่ละตำแหน่งคู่ของตัวละคร +2 ถ้าคุณแก้ไข :)
j_random_hacker

2

ด้วย regex และ ruby ​​คุณสามารถสแกนหา palindromes สั้น ๆ เช่นนี้:

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

ฉันเขียนโปรแกรม Java ต่อไปนี้ด้วยความอยากรู้อยากเห็น HTH ที่เรียบง่ายและอธิบายตัวเองได้ ขอบคุณ.

/**
 *
 * @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

ฉันถูกถามคำถามนี้เมื่อเร็ว ๆ นี้ นี่คือทางออกที่ฉัน [ในที่สุด] คิดขึ้นมา ฉันทำใน JavaScript เพราะภาษานั้นค่อนข้างตรงไปตรงมา

แนวคิดพื้นฐานคือคุณเดินสตริงโดยมองหาพาลินโดรมแบบหลายอักขระที่เล็กที่สุดเท่าที่จะเป็นไปได้ (อักขระสองหรือสามตัว) เมื่อได้สิ่งนั้นแล้วให้ขยายขอบทั้งสองด้านจนกว่าจะหยุดเป็นพาลินโดรม หากความยาวนั้นยาวกว่าความยาวที่สุดในปัจจุบันให้จัดเก็บและเคลื่อนย้ายไป

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

สิ่งนี้สามารถล้างและปรับให้เหมาะสมได้อีกเล็กน้อย แต่ควรมีประสิทธิภาพที่ค่อนข้างดีในทุกกรณี แต่ในกรณีที่เลวร้ายที่สุด (สตริงของตัวอักษรเดียวกัน)


1
เดิมทีฉันคิดว่าอัลโก # 1 ของ OP คือเวลา O (n ^ 2) แต่จริงๆแล้วมันเป็น O (n ^ 3) ที่มีหัวกระดูกดังนั้นแม้ว่าอัลกอริทึมของคุณจะไม่ได้ทำให้ทุกอย่างไปสู่ขอบเขต O (n) ที่ทำได้ ยังคงเป็นการปรับปรุง
j_random_hacker

1
คุณเรียกสิ่งนี้ว่า "ตรงไปตรงมา" แต่เต็มไปด้วยการi j l s ifบำรุงรักษา multi return points, edge case ...
v.oddou

1

สวัสดีนี่คือรหัสของฉันในการค้นหา palindrome ที่ยาวที่สุดในสตริง โปรดอ้างอิงลิงค์ต่อไปนี้เพื่อทำความเข้าใจอัลกอริทึมhttp://stevekrenzel.com/articles/longest-palnidrome

ข้อมูลการทดสอบที่ใช้คือ 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;     
  }

ฉันไม่แน่ใจว่ามันใช้ได้กับ palindromes ที่มีความยาวเท่ากันหรือเปล่า ... ยืนยันได้ไหม
st0le

สิ่งนี้ใช้ได้กับแม้แต่ palindromes คุณสามารถเรียกใช้โปรแกรมนี้และแจ้งให้เราทราบหากไม่ได้ผลสำหรับคุณเพื่อความเข้าใจเกี่ยวกับอัลกอริทึมโปรดดูที่ลิงค์ต่อไปนี้stevekrenzel.com/articles/longest-palnidrome
Mohit Bhandari

@ st0le: ตรรกะนี้ใช้ไม่ได้กับแม้แต่ palindromes แต่สามารถปรับได้สำหรับแม้แต่ palindromes ขอแสดงความเสียใจกับการเริ่มต้นก่อนหน้านี้ฉันได้รับตรรกะแล้วและฉันจะอัปเดตในอีกไม่กี่วันและเมื่อฉันมีเวลา
Mohit Bhandari

ไม่เคยอ่านความคิดเห็นก่อนหน้าของคุณจนถึงวันนี้ ... คุณไม่ได้พูดกับฉันครั้งสุดท้าย .... ใช้เวลาของคุณมันเป็นเพียงการสังเกต
st0le

2
เดิมทีฉันคิดว่าอัลโก # 1 ของ OP คือเวลา O (n ^ 2) แต่จริงๆแล้วมันเป็น O (n ^ 3) ที่มีหัวกระดูกดังนั้นแม้ว่าอัลกอริทึมของคุณจะไม่ได้ทำให้ทุกอย่างไปจนถึงขอบเขต O (n) ที่ทำได้ ยังคงเป็นการปรับปรุง
j_random_hacker

1

ดูบทความ Wikipediaในหัวข้อนี้ ตัวอย่างการใช้งานAlgorithm Java ของ Manacherสำหรับโซลูชัน linear O (n) จากบทความด้านล่าง:

นำเข้า java.util.Arrays; คลาสสาธารณะ 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

Regexpโซลูชันที่มีประสิทธิภาพซึ่งหลีกเลี่ยงการดุร้าย

เริ่มต้นด้วยความยาวสตริงทั้งหมดและลดลงเหลือ 2 อักขระจะมีอยู่ทันทีที่มีการจับคู่

สำหรับ"abaccddccefe"การทดสอบ regexp 7 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

ฟังก์ชัน

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 ได้โปรดปรับปรุงความคิดเห็นของฉันที่dailydoseofexcel.com/archives/2016/01/14/…พร้อมรหัสแก้ไขด้านบน 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

ลองใช้สตริง - "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) ทำไมต้องสร้างisPal- การดำเนินการ O (n) - เพื่อวัดความยาวเท่านั้น!? นอกจากนี้ยังมีความพยายามในการจัดการแม้แต่ palindromes เกี่ยวกับ bugginess แม้กระทั่ง palindrome: else if(input_str[i] == input_str[j])ไม่สามารถทำได้สำเร็จเนื่องจากการทดสอบเดียวกันนั้นต้องล้มเหลวในifคำสั่งก่อนหน้านี้ และมันก็เป็นบั๊กกี้อยู่ดีเพราะคุณไม่สามารถบอกได้เพียงแค่ดูอักขระ 2 ตัวที่เว้นระยะห่างกัน 2 ตำแหน่งไม่ว่าคุณจะดูที่พาลินโดรมคู่หรือคี่ (พิจารณาAAAและAAAA)
j_random_hacker

0

โค้ดต่อไปนี้จะคำนวณ Palidrom สำหรับสตริงที่มีความยาวเท่ากันและความยาวคี่

ไม่ใช่ทางออกที่ดีที่สุด แต่ใช้ได้กับทั้งสองกรณี

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. แก้ไขสตริงเพื่อแยกอักขระแต่ละตัวโดยใช้ตัวคั่น [นี่คือการรวมคี่และคู่ palindromes]
  2. ค้นหา palindromes รอบ ๆ ตัวละครแต่ละตัวที่ถือว่าเป็นศูนย์กลาง

เราสามารถหาความยาวทั้งหมดได้โดยใช้สิ่งนี้

ตัวอย่าง:

คำ = abcdcbc

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

palinCount = 1010105010301

ความยาวของพาลินโดรมที่ยาวที่สุด = 5;

Palindrome ที่ยาวที่สุด = bcdcb

คลาสสาธารณะ 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

สิ่งนี้จะส่งคืนสตริง palindrome ที่ยาวที่สุดจากสตริงที่กำหนด

-(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: การกระทำ

อินพุต: abcccbadeed เอาต์พุต: abcccba


0

นี่คือการใช้งานในจาวาสคริปต์:

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

สำหรับการแก้ปัญหาเชิงเส้นคุณสามารถใช้อัลกอริทึมของ Manacher มีอัลกอริทึมอื่นที่เรียกว่า Algorithm ของ 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();  
    }  
}  

ท่านสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับโซลูชั่นอื่น ๆ เช่นโอที่ดีที่สุด (n ^ 2) วิธีการหรือขั้นตอนวิธีการ Manacher จากบล็อกของตัวเอง


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

}

สิ่งนี้ทำให้ palindrome ทั้งหมดในสตริงไม่เพียง แต่จะยาวที่สุด
Vivek Mishra

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

#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

นี่คืออัลกอริทึมของฉัน:

1) ตั้งค่าศูนย์ปัจจุบันเป็นตัวอักษรตัวแรก

2) ขยายไปทางซ้ายและขวาพร้อมกันจนกว่าคุณจะพบ palindrome สูงสุดรอบ ๆ ศูนย์กลางปัจจุบัน

3) หากพาลินโดรมที่คุณพบมีขนาดใหญ่กว่าพาลินโดรมก่อนหน้าให้อัปเดต

4) ตั้งค่าศูนย์ปัจจุบันเป็นตัวอักษรถัดไป

5) ทำซ้ำขั้นตอนที่ 2) ถึง 4) สำหรับตัวอักษรทั้งหมดในสตริง

สิ่งนี้ทำงานใน O (n)

หวังว่าจะช่วยได้


5
พิจารณาสตริง "aaaaaa" สิ่งนี้ทำงานใน O (n ^ 2) โดยใช้อัลกอริทึมของคุณ
paislee

1
เดิมทีฉันคิดว่าอัลโก # 1 ของ OP คือเวลา O (n ^ 2) แต่จริงๆแล้วมันเป็น O (n ^ 3) ที่มีหัวกระดูกดังนั้นแม้ว่าอัลกอริทึมของคุณจะไม่ได้ทำให้ทุกอย่างไปจนถึงขอบเขต O (n) ที่ทำได้ ยังคงเป็นการปรับปรุง
j_random_hacker

นั่นคือโซลูชันการขยาย N2 แบบคลาสสิก แต่ในความเป็นจริงมันใกล้เคียงกับโซลูชันของ Manacher ตามที่อธิบายไว้ในวิดีโอนี้: youtube.com/watch?v=V-sEwsca1akความแตกต่างคือจุดที่ 4 Manacher นำข้อมูลมาใช้ซ้ำเพื่อหลีกเลี่ยงการสแกนตัวอักษรที่สแกนไปแล้วอีกครั้ง
v.oddou

-2

อ้างอิง: Wikipedia.com

อัลกอริทึมที่ดีที่สุดที่ฉันเคยพบมีความซับซ้อน 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

ทางออกของฉันคือ:

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
สิ่งนี้ใช้เวลาลูกบาศก์ในความยาวสตริงเนื่องจากการดำเนินการSubstring()และความเท่าเทียมกันของสตริง ( ==) โดยพื้นฐานแล้วมันเหมือนกับ algo # 1 ของ OP
j_random_hacker
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.