Belirli bir dizedeki en uzun palindromu döndüren bir işlev yazın


102

ör. "abaccddccefe" dizesindeki "ccddcc"

Bir çözüm düşündüm ama O (n ^ 2) zamanında çalışıyor

Algo 1:

Adımlar: Kaba kuvvet yöntemidir


  1. İ = 1 - i
    için diziler için 2 var , dizi.length -1 için j = i + 1 - j daha küçük dizi.length
  2. Bu şekilde, diziden olası her kombinasyonun alt dizesini elde edebilirsiniz.
  3. Bir dizenin palindrom olup olmadığını kontrol eden bir palindrom işlevine sahip olun
  4. yani her alt dize için (i, j) bu işlevi çağırın, eğer bu bir palindrom ise bir dizge değişkeninde saklayın
  5. Bir sonraki palindrom alt dizesini bulursanız ve geçerli olandan daha büyükse, onu geçerli alt dizeyle değiştirin.
  6. Sonunda dize değişkeninizin yanıtı olacaktır

Konular: 1. Bu algo O (n ^ 2) zamanda çalışır.

Algo 2:

  1. Dizeyi ters çevirin ve farklı dizide saklayın
  2. Şimdi her iki dizi arasında eşleşen en büyük alt dizeyi bulun
  3. Ama bu da O (n ^ 2) zamanında çalışır

Daha iyi bir zamanda çalışan bir algo düşünebilir misiniz? Mümkünse O (n) zamanı


42
Sanırım ilki O(n^2)alt dizeleri almak *O(n) palindrom olup olmadıklarını kontrol etmek için toplam O(n^3)?
Skylar Saveland

Ya palindrome ile çalıştığımı bilsem ve dizelerimi iki yarım olarak saklarsam ve sonra Java kullanırsam, O (1) işlevini kontrol etmem gerekirdi?
viki.omega9

10
İkincil algı doğru mu? Peki ya "abcdecba" dizesi. Eşleşen en büyük alt dize ("abcdecba" ve "abcedcba"): "abc" veya "cba" dır. Ancak her ikisi de palindrom değildir.
Yarneo

@Learner, sadece merak ediyorum, üstünüzdeki adımlarda for döngülerinizde hangi diziye hakemlik ediyorsunuz? Dizi ile dizeden mi bahsediyorsunuz? IP uzunluğu?
Zolt

Yanıtlar:


76

Sen kullanarak en uzun palindrom bulabilirsiniz Manacher en Algoritması içinde O(n)zaman! Uygulaması burada ve burada bulunabilir .

Girdi String s = "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE"için doğru çıktıyı bulur 1234567887654321.


3
Bunun nasıl doğrusal olduğunu anlamıyorum. Dış döngüye benzer görünen bir sınırlama ile whilegömülü bir görüyorum for.
v.oddou


9

Algo 2 tüm diziler için çalışmayabilir. İşte böyle bir "ABCDEFCBA" dizesi örneği.

Dizenin alt dizesi olarak "ABC" ve "CBA" olduğundan değil. Orijinal dizeyi tersine çevirirseniz, "ABCFEDCBA" olacaktır. ve en uzun eşleşen alt dize, bir palindrom olmayan "ABC" dir.

Ek olarak, bu en uzun alt dizenin gerçekte çalışma süresi O (n ^ 3) olan bir palindrom olup olmadığını kontrol etmeniz gerekebilir.


2
Algo 2'nin, alt dizi karakterlerinin de dizge içinde ayrılabildiği yaygın bir algoritma problemi olan "en uzun eşleşen alt dizi palindromu" için çalışması gerektiğine dikkat etmek önemlidir. Örneğin, yukarıdaki iki dizge arasındaki en uzun eşleşen alt dizi (karakter ayrımları dahil) aynı zamanda bir palindrom olan "ABCFCBA" dır :) Burada LCS problemini açıklayan bir bağlantı: ics.uci.edu/~eppstein/161/960229.html
Jake Drew

5

Sorunu anladığım kadarıyla, bir merkez indeks etrafında palindromlar bulabilir ve aramamızı merkezin sağına ve soluna her iki yönde de yayabiliriz. Bunu göz önünde bulundurarak ve girdinin köşelerinde palindrom olmadığını bilerek, sınırları 1 ve uzunluk-1 olarak belirleyebiliriz. String'in minimum ve maksimum sınırlarına dikkat ederken, maksimum üst sınır merkezimize ulaşana kadar simetrik indekslerin (sağ ve sol) konumlarındaki karakterlerin her bir merkezi konum için aynı olup olmadığını doğrularız.

Dış döngü O (n) (maks. N-2 yineleme) ve iç while döngüsü O (n) (maks. Yaklaşık (n / 2) - 1 yineleme)

İşte diğer kullanıcılar tarafından sağlanan örneği kullanan Java uygulamam.

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

Bunun çıktısı şudur:

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

6
"HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE" verirsem Çalışmıyor Ama anwer 1234567887654321
Elbek

1
@j_random_hacker hayır, bu ikinci dereceden çözümlerden biri. Bu kaplı buraya kadar expandAroundCenter.
v.oddou

@ v.oddou: Kesinlikle haklısınız ve sadece 2 iç içe döngü olduğu için O (n ^ 3) 'ü nasıl sonuçlandırdığımı bilmiyorum! Bu yanlış yorumu sileceğim ... Ancak bu çözümün bir sorunu olduğunu da fark ettim, yazarın umarım fark etmesi için ayrı bir yorum ekleyeceğim.
j_random_hacker

Daha önceki O (n ^ 3) zaman karmaşıklığı iddiam yanlıştı (buna işaret ettiğin için teşekkürler @ v.oddou!) Ama başka bir sorun daha var: bu kod çift uzunluklu palindromları dikkate almıyor. Bu ikinci, çok benzer, dış döngü ilave edilmesi suretiyle tespit edilebilir (aynı zamanda O (n bu (n ^ 2) zaman karmaşıklığı O etkilemez böylece ^ 2)) n-1 pozisyonların her biri etrafında palindrom genişler arasında her karakter çifti. +2 düzeltirseniz :)
j_random_hacker

2

regex ve ruby ​​ile aşağıdaki gibi kısa palindromları tarayabilirsiniz:

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

Aşağıdaki Java programını meraktan, basit ve kendinden açıklamalı HTH'den yazdım. Teşekkürler.

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

Geçenlerde bu soruyu sormuştum. İşte [sonunda] bulduğum çözüm. JavaScript'te yaptım çünkü o dilde oldukça basit.

Temel kavram, mümkün olan en küçük çok karakterli palindromu (iki veya üç karakterli bir) arayarak dizide yürümenizdir. Buna sahip olduğunuzda, palindrom olmayı bırakana kadar her iki taraftaki sınırları genişletin. Bu uzunluk mevcut en uzun olandan daha uzunsa, saklayın ve ilerleyin.

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

Bu kesinlikle temizlenebilir ve biraz daha optimize edilebilir, ancak en kötü durum senaryosu dışında (aynı harften bir dizi) oldukça iyi bir performansa sahip olmalıdır.


1
Başlangıçta OP'nin algo # 1'inin O (n ^ 2) zamanı olduğunu düşünmüştüm, ama aslında kafasız bir şekilde O (n ^ 3), dolayısıyla algoritmanız onu ulaşılabilir O (n) sınırına kadar tamamlamasa da, hala bir gelişme.
j_random_hacker

1
buna "basit" diyorsunuz, ancak dolu i j l s ifve bakım gerektiriyor. çoklu iade noktaları, uç durumlar ...
v.oddou

1

Merhaba İşte dizedeki en uzun palindromu bulmak için kodum. Algoritmayı anlamak için lütfen aşağıdaki bağlantıya bakın http://stevekrenzel.com/articles/longest-palnidrome

Kullanılan test verisi HYTBCABADEFGHABCDEDCBAGHTFYW12345678987654321ZWETYGDE'dir

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

Bunun eşit uzunluktaki palindromlarda işe yarayıp yaramadığından emin değilim ... onaylar mısın?
st0le

Bu, palindromlar için bile işe yarar, bu programı çalıştırabilir ve sizin için çalışıp çalışmadığını bana bildirebilirsiniz. Algoritmayı anlamak için lütfen aşağıdaki bağlantıya bakın stevekrenzel.com/articles/longest-palnidrome
Mohit Bhandari

@ st0le: Bu mantık palindromlar için bile işe yaramayacak, ancak palindromlar için bile ayarlanabilir.Kendime daha önceki topluluklar için pişmanlık duyuyorum.
Mohit Bhandari

önceki yorumunuzu bugüne kadar hiç okumamışsınız ... son kez bana hitap etmediniz .... acele etmeyin, bu sadece bir gözlemdi.
st0le

2
Başlangıçta OP'nin algo # 1'inin O (n ^ 2) zamanı olduğunu düşünmüştüm, ama aslında kafasız bir şekilde O (n ^ 3), dolayısıyla algoritmanız onu ulaşılabilir O (n) sınırına kadar tamamlamasa da, hala bir gelişme.
j_random_hacker

1

Bu konudaki Wikipedia makalesine bakın . Aşağıdaki makaleden doğrusal O (n) çözümü için Örnek Yönetici Algoritması Java uygulaması:

java.util.Arrays içe aktarın; 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

RegexpKaba kuvveti önleyen etkili bir çözüm

Tüm dize uzunluğu ile başlar ve 2 karaktere kadar aşağı doğru çalışır, eşleşme yapılır yapılmaz var olur

İçin "abaccddccefe"regexp dönmeden önce 7 eşleşmeleri testleri 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

işlevi

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, lütfen yorumumu dailydoseofexcel.com/archives/2016/01/14/… adresinde yukarıdaki revize edilmiş kodla güncelleyebilir misiniz ? 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" dizesini deneyin; Çift ve tuhaf arkadaşlar için çalışmalıdır. Mohit'e çok teşekkürler!

ad alanı std kullanarak;

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
Bu neredeyse her şeyi O (n ^ 2) zamanında yapar. Neden isPal- bir O (n) işlemi - sadece uzunluğunu ölçmek için inşa edin !? Ayrıca palindromları bile idare etmek için hatalı bir girişime sahiptir. Çift-palindrom hatasında: else if(input_str[i] == input_str[j])asla başarılı olamaz çünkü aynı test önceki ififadede başarısız olmuş olmalıdır ; ve yine de buggy çünkü sadece 2 pozisyon aralıklı 2 karaktere bakarak çift palindrom mu yoksa garip bir palindroma mı baktığınızı anlayamazsınız (düşünün AAAve AAAA).
j_random_hacker

0

Aşağıdaki kod, çift uzunluklu ve tek uzunluklu dizeler için Palidrom'u hesaplar.

En iyi çözüm değil ama her iki durumda da işe yarıyor

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. Bir ayırıcı kullanarak her karakteri ayırmak için dizeyi değiştirin [bu, tek ve çift palindromları dahil etmek içindir]
  2. Her karakterin etrafında onu bir merkez olarak ele alan palindromları bulun

Bunu kullanarak tüm uzunluktaki tüm palindromları bulabiliriz.

Örneklem :

word = abcdcbc

modifiyeString = a # b # c # d # c # b # c

palinCount = 1010105010301

en uzun palindromun uzunluğu = 5;

en uzun palindrom = 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

Bu, verilen dizeden en uzun palindrom dizesini döndürecektir

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

== ÇIKTI ===

Giriş: abcccde Çıkış: ccc

Giriş: abcccbd Çıktı: bcccb

Giriş: abedccde Çıkış: edccde

Giriş: abcccdeed Çıktı: senet

Giriş: abcccbadeed Çıkış: abcccba


0

İşte javascript'teki bir uygulama:

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


Bunun neden reddedildiğini bilmiyorum - bir cazibe gibi çalışıyor. CA teknolojileri ile röportaj yaptım gayet iyi.
alex bennett

0

Doğrusal çözüm için Manacher'in algoritmasını kullanabilirsiniz. Gusfield Algoritması olarak adlandırılan başka bir algoritma var ve aşağıda java'daki kod var:

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

En iyi O (n ^ 2) çözümü veya Manacher'in algoritması gibi diğer çözümlerle ilgili daha fazla bilgiyi kendi blogumdan bulabilirsiniz .


0

İşte bir mantık yazdım deneyin :)

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

}

bu, dizedeki tüm palindromu yalnızca en uzun olanı değil
Vivek Mishra

0

Bu Çözüm O (n ^ 2) karmaşıklıktadır. O (1) uzay karmaşıklığıdır.

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

İşte benim algoritmam:

1) mevcut merkezi ilk harf olarak ayarlayın

2) mevcut merkezin etrafındaki maksimum palindromu bulana kadar aynı anda sola ve sağa doğru genişletin

3) Bulduğunuz palindrom önceki palindromdan daha büyükse güncelleyin

4) mevcut merkezi sonraki harf olacak şekilde ayarlayın

5) dizedeki tüm harfler için 2) ila 4) adımlarını tekrarlayın

Bu, O (n) ile çalışır.

Umarım yardımcı olur.


5
"Aaaaaa" dizesini düşünün. Bu, sizin algoritmanızı kullanarak O (n ^ 2) ile çalışır.
paislee

1
Başlangıçta OP'nin algo # 1'inin O (n ^ 2) zamanı olduğunu düşünmüştüm, ama aslında kafasız bir şekilde O (n ^ 3), dolayısıyla algoritmanız onu ulaşılabilir O (n) sınırına kadar tamamlamasa da, hala bir gelişme.
j_random_hacker

Bu, klasik N2 genişletme çözümüdür. ANCAK, aslında bu, bu videoda açıklanan Manacher'in çözümüne yakın: youtube.com/watch?v=V-sEwsca1ak fark 4. nokta. Manacher, taranmış harfleri yeniden taramaktan kaçınmak için bilgileri yeniden kullanıyor.
v.oddou

-2

Referans: Wikipedia.com

Karmaşıklık O (N) ile şimdiye kadar bulduğum en iyi algoritma

 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

benim çözümüm:

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
Bu , ve string-equality ( ) işlemleri nedeniyle dize uzunluğunda kübik zaman alır . Temelde OP'nin 1. algo'suyla aynıdır. Substring()==
j_random_hacker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.