【问题标题】:Python: search longest palindromes within a word and palindromes within a word/stringPython:搜索单词中最长的回文和单词/字符串中的回文
【发布时间】:2013-06-20 15:16:49
【问题描述】:

所以这是我编写的用于在单词中查找回文的代码(检查单词中是否有回文,包括单词本身) 条件:字符之间的空格被计算并且不被忽略 示例:A but tuba 是回文,但从技术上讲,由于涉及空间,现在它不是。所以这是标准。

基于上述,以下代码通常应该可以工作。你可以自己尝试不同的测试来检查这段代码是否有任何错误。

def pal(text):
    """

    param text: given string or test
    return: returns index of longest palindrome and a list of detected palindromes stored in temp
    """
    lst = {}
    index = (0, 0)
    length = len(text)
    if length <= 1:
        return index
    word = text.lower()  # Trying to make the whole string lower case
    temp = str()
    for x, y in enumerate(word):
        # Try to enumerate over the word
        t = x
        for i in xrange(x):
            if i != t+1:
                string = word[i:t+1]
                if string == string[::-1]:
                    temp = text[i:t+1]
                    index = (i, t+1)
                    lst[temp] = index
    tat = lst.keys()
    longest = max(tat, key=len)
    #print longest
    return lst[longest], temp

这是一个已失效的版本。我的意思是我试图从中间开始,通过从头开始迭代来检测回文,并通过检查它们是否是相等的字符来检查每个更高和更低的字符索引。如果是,那么我正在检查它是否像常规回文检查一样是回文。 这就是我所做的

def pal(t):
    text = t.lower()
    lst = {}
    ptr = ''
    index = (0, 0)
    #mid = len(text)/2
    #print mid
    dec = 0
    inc = 0
    for mid, c in enumerate(text):
        dec = mid - 1
        inc = mid + 1
        while dec != 0 and inc != text.index(text[-1]):
            print 'dec {}, inc {},'.format(dec, inc)
            print 'text[dec:inc+1] {}'.format(text[dec:inc+1])
            if dec<0:
                dec = 0
            if inc > text.index(text[-1]):
                inc = text.index(text[-1])
            while text[dec] != text[inc]:
                flo = findlet(text[inc], text[:dec])
                fhi = findlet(text[dec], text[inc:])
                if len(flo) != 0 and len(fhi) != 0 and text[flo[-1]] == text[fhi[0]]:
                    dec = flo[-1]
                    inc = fhi[0]
                    print ' break if'
                    break
                elif len(flo) != 0 and text[flo[-1]] == text[inc]:
                    dec = flo[-1]
                    print ' break 1st elif'
                    break
                elif len(fhi) != 0 and text[fhi[0]] == text[inc]:
                    inc = fhi[0]
                    print ' break 2nd elif'
                    break
                else:
                    dec -= 1
                    inc += 1
                    print ' break else'
                    break
            s = text[dec:inc+1]
            print ' s {} '.format(s)
            if s == s[::-1]:
                index = (dec, inc+1)
                lst[s] = index
            if dec > 0:
                dec -= 1
            if inc < text.index(text[-1]):
                inc += 1
    if len(lst) != 0:
        val = lst.keys()
        longest = max(val, key = len)
        return lst[longest], longest, val
    else:
        return index

findlet() 好玩:

def findlet(alpha, string):
    f = [i for i,j in enumerate(string) if j == alpha]
    return f

有时它会起作用:

pal('madem')
dec -1, inc 1,
text[dec:inc+1] 
 s m 
dec 1, inc 3,
text[dec:inc+1] ade
 break 1st elif
 s m 
dec 2, inc 4,
text[dec:inc+1] dem
 break 1st elif
 s m 
dec 3, inc 5,
text[dec:inc+1] em
 break 1st elif
 s m 
Out[6]: ((0, 1), 'm', ['m'])

pal('Avid diva.')
dec -1, inc 1,
text[dec:inc+1] 
 break 2nd if
 s avid div 
dec 1, inc 3,
text[dec:inc+1] vid
 break else
 s avid  
dec 2, inc 4,
text[dec:inc+1] id 
 break else
 s vid d 
dec 3, inc 5,
text[dec:inc+1] d d
 s d d 
dec 2, inc 6,
text[dec:inc+1] id di
 s id di 
dec 1, inc 7,
text[dec:inc+1] vid div
 s vid div 
dec 4, inc 6,
text[dec:inc+1]  di
 break 1st elif
 s id di 
dec 1, inc 7,
text[dec:inc+1] vid div
 s vid div 
dec 5, inc 7,
text[dec:inc+1] div
 break 1st elif
 s vid div 
dec 6, inc 8,
text[dec:inc+1] iva
 break 1st elif
 s avid diva 
dec 8, inc 10,
text[dec:inc+1] a.
 break else
 s va. 
dec 6, inc 10,
text[dec:inc+1] iva.
 break else
 s diva. 
dec 4, inc 10,
text[dec:inc+1]  diva.
 break else
 s d diva. 
dec 2, inc 10,
text[dec:inc+1] id diva.
 break else
 s vid diva. 
Out[9]: ((0, 9), 'avid diva', ['avid diva', 'd d', 'id di', 'vid div'])

根据我提出的标准/条件:

pal('A car, a man, a maraca.')
dec -1, inc 1,
text[dec:inc+1] 
 break else
 s  
dec -1, inc 3,
text[dec:inc+1] 
 s a ca 
dec 1, inc 3,
text[dec:inc+1]  ca
 break if
 s a ca 
dec 2, inc 4,
text[dec:inc+1] car
 break else
 s  car, 
dec 3, inc 5,
text[dec:inc+1] ar,
 break else
 s car,  
dec 1, inc 7,
text[dec:inc+1]  car, a
 break 1st elif
 s a car, a 
dec 4, inc 6,
text[dec:inc+1] r, 
 break 1st elif
 s  car,  
dec 5, inc 7,
text[dec:inc+1] , a
 break 1st elif
 s ar, a 
dec 2, inc 8,
text[dec:inc+1] car, a 
 break 1st elif
 s  car, a  
dec 6, inc 8,
text[dec:inc+1]  a 
 s  a  
dec 5, inc 9,
text[dec:inc+1] , a m
 break else
 s r, a ma 
dec 3, inc 11,
text[dec:inc+1] ar, a man
 break else
 s car, a man, 
dec 1, inc 13,
text[dec:inc+1]  car, a man, 
 s  car, a man,  
dec 7, inc 9,
text[dec:inc+1] a m
 break else
 s  a ma 
dec 5, inc 11,
text[dec:inc+1] , a man
 break else
 s r, a man, 
dec 3, inc 13,
text[dec:inc+1] ar, a man, 
 break if
 s   
dec 8, inc 10,
text[dec:inc+1]  ma
 break if
 s  
dec 6, inc 4,
text[dec:inc+1] 
 break 1st elif
 s r 
dec 3, inc 5,
text[dec:inc+1] ar,
 break else
 s car,  
dec 1, inc 7,
text[dec:inc+1]  car, a
 break 1st elif
 s a car, a 
dec 9, inc 11,
text[dec:inc+1] man
 break else
 s  man, 
dec 7, inc 13,
text[dec:inc+1] a man, 
 break if
 s  
dec 5, inc 2,
text[dec:inc+1] 
 break 1st elif
 s c 
dec 1, inc 3,
text[dec:inc+1]  ca
 break if
 s a ca 
dec 10, inc 12,
text[dec:inc+1] an,
 break 1st elif
 s , a man, 
dec 4, inc 13,
text[dec:inc+1] r, a man, 
 break 1st elif
 s  car, a man,  
dec 11, inc 13,
text[dec:inc+1] n, 
 break 1st elif
 s  man,  
dec 7, inc 14,
text[dec:inc+1] a man, a
 s a man, a 
dec 6, inc 15,
text[dec:inc+1]  a man, a 
 s  a man, a  
dec 5, inc 16,
text[dec:inc+1] , a man, a m
 break else
 s r, a man, a ma 
dec 3, inc 18,
text[dec:inc+1] ar, a man, a mar
 break else
 s car, a man, a mara 
dec 1, inc 20,
text[dec:inc+1]  car, a man, a marac
 break else
 s a car, a man, a maraca 
dec 12, inc 14,
text[dec:inc+1] , a
 break 1st elif
 s an, a 
dec 9, inc 15,
text[dec:inc+1] man, a 
 break if
 s  
dec 7, inc 2,
text[dec:inc+1] 
 break 1st elif
 s c 
dec 1, inc 3,
text[dec:inc+1]  ca
 break if
 s a ca 
dec 13, inc 15,
text[dec:inc+1]  a 
 s  a  
dec 12, inc 16,
text[dec:inc+1] , a m
 break 1st elif
 s man, a m 
dec 8, inc 17,
text[dec:inc+1]  man, a ma
 break 1st elif
 s a man, a ma 
dec 6, inc 18,
text[dec:inc+1]  a man, a mar
 break 1st elif
 s r, a man, a mar 
dec 3, inc 19,
text[dec:inc+1] ar, a man, a mara
 s ar, a man, a mara 
dec 2, inc 20,
text[dec:inc+1] car, a man, a marac
 s car, a man, a marac 
dec 1, inc 21,
text[dec:inc+1]  car, a man, a maraca
 break 1st elif
 s a car, a man, a maraca 
dec 14, inc 16,
text[dec:inc+1] a m
 break 1st elif
 s man, a m 
dec 8, inc 17,
text[dec:inc+1]  man, a ma
 break 1st elif
 s a man, a ma 
dec 6, inc 18,
text[dec:inc+1]  a man, a mar
 break 1st elif
 s r, a man, a mar 
dec 3, inc 19,
text[dec:inc+1] ar, a man, a mara
 s ar, a man, a mara 
dec 2, inc 20,
text[dec:inc+1] car, a man, a marac
 s car, a man, a marac 
dec 1, inc 21,
text[dec:inc+1]  car, a man, a maraca
 break 1st elif
 s a car, a man, a maraca 
dec 15, inc 17,
text[dec:inc+1]  ma
 break 1st elif
 s a ma 
dec 13, inc 18,
text[dec:inc+1]  a mar
 break 1st elif
 s r, a man, a mar 
dec 3, inc 19,
text[dec:inc+1] ar, a man, a mara
 s ar, a man, a mara 
dec 2, inc 20,
text[dec:inc+1] car, a man, a marac
 s car, a man, a marac 
dec 1, inc 21,
text[dec:inc+1]  car, a man, a maraca
 break 1st elif
 s a car, a man, a maraca 
dec 16, inc 18,
text[dec:inc+1] mar
 break 1st elif
 s r, a man, a mar 
dec 3, inc 19,
text[dec:inc+1] ar, a man, a mara
 s ar, a man, a mara 
dec 2, inc 20,
text[dec:inc+1] car, a man, a marac
 s car, a man, a marac 
dec 1, inc 21,
text[dec:inc+1]  car, a man, a maraca
 break 1st elif
 s a car, a man, a maraca 
dec 17, inc 19,
text[dec:inc+1] ara
 s ara 
dec 16, inc 20,
text[dec:inc+1] marac
 break 1st elif
 s car, a man, a marac 
dec 1, inc 21,
text[dec:inc+1]  car, a man, a maraca
 break 1st elif
 s a car, a man, a maraca 
dec 18, inc 20,
text[dec:inc+1] rac
 break 1st elif
 s car, a man, a marac 
dec 1, inc 21,
text[dec:inc+1]  car, a man, a maraca
 break 1st elif
 s a car, a man, a maraca 
dec 19, inc 21,
text[dec:inc+1] aca
 s aca 
dec 21, inc 23,
text[dec:inc+1] a.
 break else
 s ca. 
dec 19, inc 23,
text[dec:inc+1] aca.
 break else
 s raca. 
dec 17, inc 23,
text[dec:inc+1] araca.
 break else
 s maraca. 
dec 15, inc 23,
text[dec:inc+1]  maraca.
 break else
 s a maraca. 
dec 13, inc 23,
text[dec:inc+1]  a maraca.
 break else
 s , a maraca. 
dec 11, inc 23,
text[dec:inc+1] n, a maraca.
 break else
 s an, a maraca. 
dec 9, inc 23,
text[dec:inc+1] man, a maraca.
 break else
 s  man, a maraca. 
dec 7, inc 23,
text[dec:inc+1] a man, a maraca.
 break else
 s  a man, a maraca. 
dec 5, inc 23,
text[dec:inc+1] , a man, a maraca.
 break else
 s r, a man, a maraca. 
dec 3, inc 23,
text[dec:inc+1] ar, a man, a maraca.
 break else
 s car, a man, a maraca. 
dec 1, inc 23,
text[dec:inc+1]  car, a man, a maraca.
 break else
 s a car, a man, a maraca. 
Out[8]: ((13, 16), ' a ', ['', ' a ', 'c', ' ', 'aca', 'ara', 'r'])

有时,它根本不起作用:

    pal('madam')
    dec -1, inc 1,
    text[dec:inc+1] 
     s m 
    dec 1, inc 3,
    text[dec:inc+1] ada
     break 1st elif
     s m 
    dec 2, inc 4,
    text[dec:inc+1] dam
     break 1st elif
     s m 
    dec 3, inc 5,
    text[dec:inc+1] am
     break 1st elif
     s m 
    Out[5]: ((0, 1), 'm', ['m'])

现在考虑到 madam 是一个非常好的回文,它应该可以工作,而且我还没有测试过很多情况,以找出它没有检测到的其他合法回文。

Q1:为什么有时检测不到?

Q2:我想为此优化我的第二个代码。有输入吗?

Q3:有什么比我的第一个迭代多次的代码更高效的方法?

【问题讨论】:

    标签: python palindrome


    【解决方案1】:

    您的解决方案对我来说似乎有点复杂。只需查看所有可能的子字符串并单独检查它们:

    def palindromes(text):
        text = text.lower()
        results = []
    
        for i in range(len(text)):
            for j in range(0, i):
                chunk = text[j:i + 1]
    
                if chunk == chunk[::-1]:
                    results.append(chunk)
    
        return text.index(max(results, key=len)), results
    

    text.index() 只会找到第一次出现的最长回文,所以如果你想要最后一次出现,请将其替换为 text.rindex()

    【讨论】:

    • 是的,这太乱了,尤其是。对于我尝试使用 func findlet() 搜索单词中给定字母的所有索引的第二个代码。我过于复杂。很棒
    • 虽然我确实明白我只需要将 enumerate(word) 更改为 range(len(word)) ,然后您的代码和我的第一个代码相同。所以我想我会注意更多如果有有效的解决方案
    • 提供一些背景知识,尝试解决 leetcode 问题。根据 leet 代码,该解决方案遗漏了两个极端情况:(a) 如果字符串只有一个/两个字符。例如,如果字符串是“a”或“aa”,则回文是“a”或“aa”; (b) 如果一个字符串有 4 个唯一字符,如“abcd”,则回文是“a”。
    【解决方案2】:

    以下函数返回给定字符串中包含的最长回文。只是略有不同,它使用itertools,正如this answer 中所建议的那样。抽象出组合生成是有价值的。它的时间复杂度显然仍然是立方的。它可以根据需要轻松调整以返回索引和/或回文列表。

    import itertools
    
    def longest_palindrome(s):
        lp, lp_len = '', 0
        for start, stop in itertools.combinations(range(len(s)+1), 2):
            ss = s[start:stop]  # substring
            if (len(ss) > lp_len) and (ss == ss[::-1]):
                lp, lp_len = ss, len(ss)
        return lp
    

    【讨论】:

    • 如果我需要所有最长的回文怎么办。目前,它只返回一个最长的回文。
    【解决方案3】:

    如果您喜欢递归解决方案,我已经编写了递归版本。它也很直观。

    def palindrome(s):
      if len(s) <= 1:
        return s
      elif s[0] != s[-1]:
        beginning_palindrome = palindrome(s[:-1])
        ending_palindrome = palindrome(s[1:])
        if len(beginning_palindrome) >= len(ending_palindrome):
          return beginning_palindrome
        else:
          return ending_palindrome
      else:
        middle_palindrome = palindrome(s[1:-1])
        if len(middle_palindrome) == len(s[1:-1]):
            return s[0] + middle_palindrome + s[-1]
        else:
            return middle_palindrome
    

    【讨论】:

      【解决方案4】:

      下面是我为同一个问题编写的代码。它可能没有真正优化,但就像一个魅力。对于初学者来说也很容易理解

      def longestPalindrome(s):
              pal = []
              longestpalin = s
              l = list(s)
              if len(s)>0:
                  if len(s)==2:
                      p = l
                      if p[0]==p[1]:
                          return s
                      else:
                          return l[0]
                  else:
                      for i in range(0,len(l)):
                          for j in range(i+1,len(l)+1):
                              p = l[i:j]
                              if p == p[::-1]:
                                  if len(p)>len(pal):
                                      pal = p
                                      p = ''.join(p)
                                      longestpalin = p
                  return longestpalin
              else:
                  return longestpalin
      

      【讨论】:

        【解决方案5】:

        Python 3 解决方案:(不是最快的)

        class Solution:
            def longestPalindrome(self, s: str) -> str:
        
                if s == "":
                    return ""
                if len(s) == 1: 
                    return s
                if len(s) == 2:
                    if s == s[::-1]:
                        return s
                    else:
                        return s[0]
        
        
                results = []
        
                for i in range(len(s)):
                    for j in range(0, i):
                        chunk = s[j:i + 1]
        
                        if chunk == chunk[::-1]:
                            results.append(chunk)
                if results:       
                    return max(results, key=len)
                else:
                    return s[0]
        

        【讨论】:

          【解决方案6】:
          a = "xabbaabba"  # Provide any string
          
          count=[]
          for j in range(len(a)):
              for i in range(j,len(a)):
                  if a[j:i+1] == a[i:j-1:-1]:      
                      count.append(i+1-j)
          
          print("Maximum size of Palindrome within String is :", max(count))
          

          【讨论】:

          • 仅代码答案本身并不是很有用。如果您可以添加一些详细信息来解释它如何/为什么回答问题,这将有所帮助。
          • 虽然这段代码可能有助于解决问题,但它并没有解释为什么和/或如何回答问题。提供这种额外的背景将显着提高其长期教育价值。请edit您的答案添加解释,包括适用的限制和假设。
          【解决方案7】:

          以下代码可用于查找最长的回文子串:

          string = "sensmamstsihbalabhismadamsihbala"
          string_shortener = ""
          pres = 0
          succ = 3
          p_temp=0
          s_temp=0
          longest = ""
          for i in range(len(string)-2):
              string_shortener = string[pres:succ]
              if(string_shortener==string_shortener[::-1]):
                 p_temp = pres
                 s_temp = succ
                 for u in range(1000):
                     p_temp-=1
                     s_temp +=1
                     string_shortener = string[p_temp:s_temp]
                     if(string_shortener == string_shortener[::-1]):
                          if len(string_shortener)>len(longest):
                              longest = string_shortener
                      else:
                          break
              pres+=1
              succ+=1
          print(longest)
          

          【讨论】:

          • 只给出代码,没有任何解释不符合堆栈溢出标准
          【解决方案8】:
          inputStr = "madammmdd"
          outStr = ""
          uniqStr = "".join(set(inputStr))
          flag = False
          for key in uniqStr:
             val = inputStr.count(key)
             if val % 2 !=0:
                if not flag:
                   outStr = outStr[:len(outStr)/2]+key+outStr[len(outStr)/2:]
                   flag=True
                val-=1
             outStr=key*(val/2)+outStr+key*(val/2)
          print outStr
          

          【讨论】:

            【解决方案9】:

            我在这个字符串参数“s”中将函数名设为 maxpalindrome(s)。这个函数将返回最长可能的回文子串和子串的长度...

            def maxpalindrome(s):
            if len(s) == 1 or s == '':
                return str(len(s)) + "\n" + s
            else:
                if s == s[::-1]:
                    return str(len(s)) + "\n" + s
                else:
                    for i in range(len(s)-1, 0, -1):
                        for j in range(len(s)-i+1):
                            temp = s[j:j+i]
                            if temp == temp[::-1]:
                                return str(len(temp)) +"\n"+temp
            

            【讨论】:

            • 这是和上面一样的解决方案
            【解决方案10】:

            这是另一种简洁明了的方法,取自 P. Norvig 的优秀在线课程Design of Computer Programs。它遍历字符串中的所有字符,并尝试将字符串“增长”到左侧和右侧。

            def longest_sub_palindrome_slice(text):
                "Return (i,j) such that text[i,j] is the longest palindrome in text"
                if text == '': return (0, 0)
                def length(slice): a,b = slice; return b-a
                candidates = [grow(text, start, end)
                             for start in range(len(text))
                             for end in (start, start + 1)]
                return max(candidates, key=length)
            
            def grow(text, start, end):
                "Start with a 0- or 1- length palindrome; try to grow a bigger one"
                while (start > 0 and end < len(text)
                       and text[start-1].upper() == text[end].upper()):
                    start -= 1; end += 1
                return (start, end)
            

            【讨论】:

              【解决方案11】:
              value ="Madamaaamadamaaaacdefgv"
              longestPalindrome =""
              lenght =0;
              for i in range(len(value)):
                      for j in range(0, i):
                          array = value[j:i + 1]
                          if (array == array[::-1] and len(longestPalindrome) < len(array)):
                              longestPalindrome =array
              print(longestPalindrome)
              

              【讨论】:

                【解决方案12】:

                这可以使用一个窗口将其悬停在单词上来识别,因为我们只对找到最长的回文感兴趣,所以我们可以从单词本身的大小开始窗口大小,并通过检查所有可能性逐渐减小它被窗口覆盖的块。当我们找到第一个回文块时,我们可以停止算法,这也是给定单词中最长的回文块。

                word = input("Word:").lower()
                window_size = len(word)
                found = False
                while window_size > 1 and not found:
                    start = 0
                    while start <= len(word) - window_size and not found:
                        window = word[start:start+window_size]
                        if window[::-1] == window:
                            print("Longest Palindrome :" , window)
                            found = True
                        start += 1
                    window_size -= 1
                

                【讨论】:

                  【解决方案13】:
                  s='stresseddesserts'
                  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]
                  

                  {'tresseddessert': 14, 'seddes': 6, 'esseddesse': 10, 'esse': 4, 'stresseddesserts': 16, 'resseddesser': 12, 'edde': 4, 'sseddess': 8}

                  ('强调的甜点', 16)

                  【讨论】:

                    【解决方案14】:
                    def longestPalindrome(s):
                            temp = ""
                            for i in range(len(s)):
                                for j in range(len(s)-1,i-1,-1):
                                    if s[i] == s[j]:
                                        m = s[i:j+1]
                                        if m == m[::-1]:
                                            if len(temp) <= len(m):
                                                temp = m
                            return temp
                    

                    【讨论】:

                    • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
                    【解决方案15】:

                    我不得不同意解决方案可能看起来很复杂,我认为最好的解决方案是在子序列中找到最大的回文,(考虑中间的字符,例如在“字符”中最大的回文应该是 carac)是:

                    def find_char_backwards(a, c):
                    for i in range(len(a) - 1, -1,-1):
                        if a[i] == c:
                            index=i
                            return True, index
                    
                    return False, 0
                    
                    def longest_palindorme(a):
                    if len(a) < 2:
                        return a
                    else:
                        c=a[0]
                        (exist_char,index) = find_char_backwards(a[1:],c)
                        if exist_char:
                            palindrome=[c] + longest_palindorme(a[1:index+1]) + [c]
                        else:
                            palindrome=[]
                        rest_palidorme=longest_palindorme(a[1:])
                    
                    if len(palindrome)>len(rest_palidorme):
                        return palindrome
                    else:
                        return rest_palidorme
                    

                    其中 a 是一个数组,此解决方案使用递归和动态规划

                    【讨论】:

                      【解决方案16】:

                      使用嵌套循环:

                      for x in range(len(body)):
                          for y in range(len(body)):
                          ...
                      

                      【讨论】:

                      • 这可能会有所作为,但目前尚不清楚它如何以任何方式解决问题。
                      猜你喜欢
                      • 2020-03-04
                      • 1970-01-01
                      • 2022-01-01
                      • 1970-01-01
                      • 2014-10-27
                      • 1970-01-01
                      • 2022-01-09
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多