주어진 문자열에서 가장 긴 회문을 반환하는 함수 작성


102

예 : "abaccddccefe"문자열의 "ccddcc"

해결책을 생각했지만 O (n ^ 2) 시간에 실행됩니다.

알고 1 :

단계 : 무차별 대입 방법


  1. i = 1 ~ i에 대해 2 개의 for 루프 가 array.length보다 작습니다.
    j = i + 1 ~ j가 array.length보다 작 으면 -1 입니다.
  2. 이렇게하면 배열에서 가능한 모든 조합의 하위 문자열을 얻을 수 있습니다.
  3. 문자열이 회문인지 확인하는 회문 기능이 있습니다.
  4. 따라서 모든 하위 문자열 (i, j)에 대해이 함수를 호출합니다. 회문이면 문자열 변수에 저장합니다.
  5. 다음 회문 부분 문자열을 찾고 현재 문자열보다 크면 현재 문자열로 바꿉니다.
  6. 마지막으로 문자열 변수에 답이 있습니다.

문제 : 1.이 알고리즘은 O (n ^ 2) 시간에 실행됩니다.

알고 2 :

  1. 문자열을 뒤집어 다른 배열에 저장하십시오.
  2. 이제 두 배열 사이에서 가장 일치하는 부분 문자열을 찾으십시오.
  3. 하지만 이것도 O (n ^ 2) 시간에 실행됩니다.

더 나은 시간에 실행되는 알고리즘을 생각할 수 있습니까? 가능하면 O (n) 시간


42
첫 번째 는 회문인지 확인 O(n^2)하기 위해 하위 문자열 *을 가져 오는 것 O(n)입니다 O(n^3).
Skylar Saveland 2012 년

회문으로 작업하고 문자열을 절반으로 저장하고 Java를 사용하는 경우 O (1) 함수를 확인하면 어떻게됩니까?
viki.omega9 2013 년

10
secong algo가 맞습니까? "abcdecba"문자열은 어떻습니까? 일치하는 가장 큰 하위 문자열은 ( "abcdecba"대 "abcedcba") : "abc"또는 "cba"입니다. 그러나 둘 다 회문이 아닙니다.
Yarneo 2013-07-13

@Learner, 궁금한 점이 있습니다. for 루프에서 어떤 배열을 참조하고 있습니까? 배열로 문자열을 참조하고 있습니까? string.length?
Zolt 2013

답변:


76

Manacher 's Algorithm 을 사용하여 가장 긴 회문을 찾을 수 있습니다 O(n)! 구현은 여기여기 에서 찾을 수 있습니다 .

입력의 String s = "HYTBCABADEFGHABCDEDCBAGHTFYW1234567887654321ZWETYGDE"경우 올바른 출력을 찾습니다 1234567887654321.


3
나는 이것이 어떻게 선형인지 이해하지 못합니다. 외부 루프와 비슷한 경계가 있는에 while포함 된 것을 봅니다 for.
v.oddou jul.


9

Algo 2는 모든 문자열에서 작동하지 않을 수 있습니다. 다음은 이러한 문자열 "ABCDEFCBA"의 예입니다.

문자열의 하위 문자열로 "ABC"및 "CBA"가있는 것은 아닙니다. 원래 문자열을 반대로하면 "ABCFEDCBA"가됩니다. 가장 긴 일치하는 부분 문자열은 회문이 아닌 "ABC"입니다.

이 가장 긴 일치 하위 문자열이 실제로 실행 시간이 O (n ^ 3) 인 회문인지 추가로 확인해야 할 수도 있습니다.


2
Algo 2는 문자열 내에서 하위 시퀀스 문자를 분리 할 수있는 일반적인 알고리즘 문제인 "가장 긴 일치 하위 시퀀스 회문"에 대해 작동해야합니다. 예를 들어, 위의 두 문자열 사이에서 가장 긴 일치 하위 시퀀스 (문자 분리 포함)는 "ABCFCBA"이며 회문이기도합니다. :) 여기 LCS 문제를 설명하는 링크 : ics.uci.edu/~eppstein/161/960229.html
Jake Drew

5

내가 문제를 이해하는 한, 우리는 중앙 색인 주위에서 회문을 찾을 수 있고 중앙의 오른쪽과 왼쪽으로 검색 범위를 둘 수 있습니다. 입력의 모서리에 회문이 없다는 것을 알고 있으므로 경계를 1 및 길이 -1로 설정할 수 있습니다. String의 최소 및 최대 경계에주의를 기울이면서 대칭 인덱스 (오른쪽 및 왼쪽) 위치의 문자가 최대 상한 중심에 도달 할 때까지 각 중앙 위치에 대해 동일한 지 확인합니다.

외부 루프는 O (n) (최대 n-2 회 반복)이고 내부 while 루프는 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 nope, 그것은 2 차 솔루션 중 하나입니다. 그것은 덮여 여기expandAroundCenter.
v.oddou

@ v.oddou : 당신이 절대적으로 옳고, 중첩 된 루프가 2 개뿐이라는 점을 감안할 때 O (n ^ 3)를 어떻게 결론을 내 렸는지 모르겠습니다! 이 잘못된 댓글은 삭제하겠습니다.하지만이 솔루션에 문제가 있다는 것도 알아 챘습니다. 작성자가 알아 차릴 수 있도록 별도의 댓글을 달겠습니다.
j_random_hacker jul.

O (n ^ 3) 시간 복잡도에 대한 나의 이전 주장은 잘못되었지만 (이것을 지적 해준 @ v.oddou에게 감사드립니다!) 또 다른 문제가 있습니다 : 이 코드는 짝수 길이의 회문을 고려하지 않습니다. 이것은 제 2의 매우 유사 외부 루프를 부가함으로써 해결 될 수있다 (또한, O (N은 (N ^ 2) 시간 복잡도 O에 영향을주지 않도록 ^ 2)) 즉, N-1의 각 위치 주위 회문 확장 사이 각 문자 쌍. 이 당신이 고칠 경우 :
j_random_hacker

2

정규식과 루비를 사용하면 다음과 같은 짧은 회문을 스캔 할 수 있습니다.

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

나는 호기심, 간단하고 자명 한 HTH로 다음 Java 프로그램을 작성했습니다. 감사.

/**
 *
 * @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로했습니다.

기본 개념은 가능한 가장 작은 다중 문자 회문 (2 또는 3 문자)을 찾기 위해 현을 걷는 것입니다. 일단 그것이 회문이 될 때까지 양쪽의 경계를 확장하십시오. 그 길이가 현재 가장 긴 길이보다 길면 저장하고 따라 이동하십시오.

// 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
나는 원래 OP의 algo # 1이 O (n ^ 2) 시간이라고 생각했지만 실제로 뼈대가 O (n ^ 3)이므로 알고리즘이 달성 가능한 O (n) 경계까지 도달하지 못하더라도 그것은 여전히 ​​개선입니다.
j_random_hacker

1
당신은 이것을 "직접적"이라고 부르지 만 그것은 i j l s if상태 유지로 가득 차 있습니다. 멀티 반환 포인트, 에지의 경우 ...
v.oddou

1

안녕 여기 문자열에서 가장 긴 회문을 찾는 코드가 있습니다. 알고리즘을 이해하려면 다음 링크를 참조하십시오. 참조하십시오. 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;     
  }

이것이 짝수 길이의 회문에서도 작동하는지 잘 모르겠습니다 ... 확인해 주시겠습니까?
st0le

이것은 회문에서도 작동합니다.이 프로그램을 실행하고 작동하지 않는 경우 알려주십시오. 알고리즘에 대한 이해는 다음 링크를 참조하십시오. stevekrenzel.com/articles/longest-palnidrome
Mohit Bhandari

@ st0le :이 논리는 회문에서도 작동하지 않지만 회문에서도 조정할 수 있습니다. 이전 명령에 대해 친절하게 후회합니다. 논리를 얻었고 시간이되면 며칠 후에 업데이트 할 것입니다.
모 히트 반 다리

오늘까지 당신의 이전 댓글을 읽지 않았습니다. 당신은 저번에 저에게 말하지 않았습니다. ... 시간을내어, 그것은 단지 관찰이었습니다.
st0le 2011 년

2
나는 원래 OP의 algo # 1이 O (n ^ 2) 시간이라고 생각했지만 실제로 뼈대가 O (n ^ 3)이므로 알고리즘이 달성 가능한 O (n) 경계까지 도달하지는 않지만 그것은 여전히 ​​개선입니다.
j_random_hacker

1

이 주제에 대한 Wikipedia 기사 를 참조하십시오 . 아래 기사에서 선형 O (n) 솔루션에 대한 샘플 Manacher의 알고리즘 Java 구현 :

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

1

효율적인 Regexp무차별 대입을 피하는 솔루션

전체 문자열 길이로 시작하여 2 자까지 작동하며 일치하는 즉시 존재합니다.

"abaccddccefe"정규 표현식의 경우 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) 작업-길이를 측정하기 위해!? 또한 회문도 처리하려는 버그가 있습니다. 짝수 회문 버그에 대해 : else if(input_str[i] == input_str[j])이전 if진술 에서 동일한 테스트가 실패 했어야하므로 성공할 수 없습니다 . 그리고 어쨌든 버그가 있습니다. 짝수 회문을보고 있는지 또는 이상한 회문을보고 있는지 ( AAA및 고려 AAAA) 2 위치 간격으로 떨어져있는 2 개의 문자를 보는 것만으로는 알 수 없기 때문 입니다.
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. 구분 기호를 사용하여 각 문자를 구분하도록 문자열을 수정합니다 [홀수 및 짝수 회문을 통합하는 것입니다]
  2. 중심으로 취급하는 각 캐릭터 주변의 회문을 찾습니다.

이것을 사용하여 모든 길이의 모든 회문을 찾을 수 있습니다.

샘플 :

단어 = abcdcbc

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

palinCount = 1010105010301

가장 긴 회 문의 길이 = 5;

가장 긴 회문 = bcdcb

public class MyLongestPalindrome {

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

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

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

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

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

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

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

    }

}

}


0

주어진 문자열에서 가장 긴 회문 문자열을 반환합니다.

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

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

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

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


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

    NSString *strMaxPalindrom = @"";

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

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

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

            if([self isPalindromString:strSub]){

                if(strSub.length>strMaxPalindrom.length){

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

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

== 출력 ===

입력 : abcccde 출력 : ccc

입력 : abcccbd 출력 : bcccb

입력 : abedccde 출력 : edccde

입력 : abcccdeed 출력 : deed

입력 : abcccbadeed 출력 : abcccba


0

다음은 자바 스크립트로 구현 된 것입니다.

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의 알고리즘을 사용할 수 있습니다. Gusfield의 Algorithm이라는 또 다른 알고리즘이 있으며 아래는 java의 코드입니다.

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

    public String longestPalindrome(String s) {  

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

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

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

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

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

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

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

        return result.toString();  
    }  
}  

내 블로그 에서 최고의 O (n ^ 2) 솔루션이나 Manacher의 알고리즘과 같은 다른 솔루션에 대해 자세히 알아볼 수 있습니다 .


0

여기에 논리를 작성했습니다 :)

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

}

이 가장 긴뿐만 아니라 캐릭터의 모든 회문 제공
비벡 미 쉬라

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) 현재 중심 주변의 최대 회문을 찾을 때까지 동시에 왼쪽과 오른쪽으로 확장

3) 찾은 회문이 이전 회문보다 크면 업데이트하십시오.

4) 현재 중심을 다음 문자로 설정

5) 문자열의 모든 문자에 대해 2) ~ 4) 단계를 반복합니다.

이것은 O (n)에서 실행됩니다.

도움이되기를 바랍니다.


5
문자열 "aaaaaa"를 고려하십시오. 이것은 알고리즘을 사용하여 O (n ^ 2)에서 실행됩니다.
paislee

1
나는 원래 OP의 algo # 1이 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
이는 및 문자열 같음 ( ) 연산으로 인해 문자열 길이에 3 차 시간 이 걸립니다 . 기본적으로 OP의 algo # 1과 동일합니다. Substring()==
j_random_hacker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.