使用python查找字符串的回文

时间:2019-04-03 02:47:35

标签: python

我想从给定的字符串中找到最长的回文。

然后打印

lines = "forgeeksskeegfor"
length = len(lines)
a = [lines[i:j+1] for i in range(length) for j in range(i, length)]

total = []
for string in a:
    list(string).reverse()
    reverse_String = "".join(string)

    if reverse_String == string.lower():
      total.append(reverse_String)
print(max(total))

我当前的输出:     sskeegfor

预期应为:

geeksskeeg

这是长度10,最长的

6 个答案:

答案 0 :(得分:1)

有两种回文场景:偶数回文(例如中午)和奇数回文(例如雷达)。字符串中的每个位置只有两个可能的(最长)回文。因此,对于每个位置,您只需通过前后比较字符即可找到以该位置为中心的最长的偶数和奇数回文率。

s = "forgeeksskeegfor"

from os import path 
longest = ""
for i in range(1,len(s)-1):
    if min(i,len(s)-i)*2+1 <= len(longest): continue
    for odd in [1,0]:
        if s[i+odd] != s[i-1]: continue
        halfSize = len(path.commonprefix([s[i+odd:],s[:i][::-1]])) 
        if 2*halfSize + odd > len(longest):
            longest = s[i-halfSize:i+halfSize+odd];break
print(longest) # geeksskeeg

注意:这可以进一步优化,但在大多数情况下会在O(n)时间内响应,或者在字符串包含很长链的最坏情况下,响应时间最多为O(n ^ 2/2)。相同的字符(或仅一个重复的字符)

更新

为了最小化相同字符的长链的影响,潜在回文的中心位置顺序可以遵循二进制搜索模式。下面的binRange()生成器可用于在主循环中将range(1,len(s)-1)替换为binRange(1,len(s)-1)。这样可以确保在早期发现更长的回文,而在随后的迭代中可以缩短较短的嵌入式回文。

from itertools import zip_longest
def binRange(lo,hi=None):
    if hi is None: lo,hi = 0,lo
    if hi <= lo: return
    mid = (lo+hi-1)//2
    yield mid
    for a,b in zip_longest(binRange(lo,mid),binRange(mid+1,hi),fillvalue=None):
        if a is not None: yield a
        if b is not None: yield b

答案 1 :(得分:0)

您应该寻找最大长度,而不是寻找“字符串”列表的最大值。 根据您的方法。

lines = "forgeeksskeegfor"
length = len(lines)
a = [lines[i:j+1] for i in range(length) for j in range(i, length)]

total = []
for string in a:
    if string == string[::-1]:
        total.append(string)
max_len = max( [ len(x) for x in total ] )
# result list will contain the longest pallindroms
result_list = [ x for x in total if len(x) == max_len ]

回文检查中存在一些缺陷。

for string in a:
    # the below line will not change anything
    # you are just converting a string to list on the fly 
    # reversing it ,but not storing it somewhere
    list(string).reverse()
    # string is still string of a , and reverse_String and string
    # both will be same.
    reverse_String = "".join(string)

    # not sure why are you converting to lower here
    if reverse_String == string.lower():
      total.append(reverse_String)Hope it helps

希望有帮助。

答案 2 :(得分:0)

这可以通过动态编程来解决

当字符串中没有回文时,以下代码的最坏运行时间为2 ^ n,因此它将尝试所有可能的解决方案。
但是当发现回文时,它的性能会提高。

def find_pal(string, start, end):
    # base case
    if end - start <= 1:
        return (start, end)
    # if a palindrome shows:
    elif string[start] == string[end]:
        # check if its substring is a palindrome also
        next_pal = find_pal(string, start + 1, end - 1)
        if next_pal == (start + 1, end - 1):
            # if it is, then return the longer
            return (start, end)
        else:
            # if it is not, still return any smaller palindrome in string
            return next_pal
    else:
        # if this string is not a palindrome, check for a smaller in a  substring
        next_pal1 = find_pal(string, start + 0, end - 1)
        next_pal2 = find_pal(string, start + 1, end - 0)
        if next_pal1[1] - next_pal1[0] > next_pal2[1] - next_pal2[0]:
            return next_pal1
        else:
            return next_pal2


def find_greatest_pal(string):
    pal_pair = find_pal(string, 0, len(string)-1)
    return string[pal_pair[0]:pal_pair[1]+1]


print(find_greatest_pal("forgeeksskeegfor"))

答案 3 :(得分:0)

这个想法是遍历字符串并生成所有从中心开始到两侧的回文。如果发现回文大于当前长度,则将其替换为新回文。

def longestPalindrome(s):
    ans = ""
    for i in range(len(s)):
        for k in range(2):
            temp = helper(s, i, i + k)
            if len(temp) > len(ans):
                ans = temp
    return ans

def helper(s, l, r):
    while l >= 0 and r < len(s) and s[r] == s[l]:
        l -= 1
        r += 1
    return s[l+1:r]

用法:

print(longestPalindrome('forgeeksskeegfor'))
geeksskeeg

答案 4 :(得分:0)

有一个简单的方法,此功能可以为您提供帮助:

def longest_palindrome(text):
    text = text.lower()
    longest = ""
    for i in range(len(text)):
        for j in range(0, i):
            chunk = text[j:i + 1]
            if chunk == chunk[::-1]:
                if len(chunk) > len(longest):
                    longest = chunk
    return longest


print(longest_palindrome("forgeeksskeegfor"))

答案 5 :(得分:0)

假设子字符串的长度为1个字符(可以在检查长度条件下轻松修改),并且可能存在多个具有相同长度的最长字符串:

def longest_substring(string):
    longest = ""
    for i in range(len(string)):
        for j in range(i + 1, len(string) + 1):
            sub = ''.join(string[i:j])
            if str(sub) == str(sub)[::-1]:
                if len(sub) > len(longest):
                    longest = sub

    return longest