Python: search longest palindromes within a word and palindromes within a word/string

佐手、 提交于 2019-11-26 20:50:16

问题


So here is a code i have written to find palindromes within a word (To check if there are palindromes within a word including the word itself) Condition: spaces inbetween characters are counted and not ignored Example: A but tuba is a palindrome but technically due to spaces involved now it isn't. so that's the criteria.

Based on above, the following code usually should work. You can try on your own with different tests to check out if this code gives any error.

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

And here is a defunct version of it. What I mean is I have tried to start out from the middle and detect palindromes by iterating from the beginning and checking for each higher and lower indices for character by checking if they are equal characters. if they are then i am checking if its a palindrome like a regular palindrome check. here's what I have done

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() fun:

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

Sometimes it works:

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

And based on the Criteria/Condition i have put:

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

Sometimes, it doesn't work at all:

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

Now considering madam is a very nice palindrome it should work and there are many cases which i haven't tested myself to find out what other legitimate palindromes it doesn't detect.

Q1: Why is it sometimes not detecting?

Q2: I would like to optimize my second code for that matter. Any inputs?

Q3: What better approach is there for a much much more efficient code than my First code which iterates many a times?


回答1:


Your solution seems a bit complicated to me. Just look at all of the possible substrings and check them individually:

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() will only find the first occurrence of the longest palindrome, so if you want the last, replace it with text.rindex().




回答2:


The following function returns the longest palindrome contained in a given string. It is just slightly different in that it uses itertools as suggested in this answer. There is value in abstracting away the combination generation. Its time complexity is evidently still cubic. It can trivially be adapted as needed to return the index and/or the list of palindromes.

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:


If you like the recursive solution, I have written a recursive version. It is also intuitive.

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:


below is a code I wrote for the same question. It might not be really optimized but works like a charm. Pretty easy to understand too for beginners

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:


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



回答6:


Here's a code you can use for finding the longest palindromic substring:

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)



回答7:


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



回答8:


I have made function name as maxpalindrome(s) in this one string argument 's'. This function will return longest possible palindrome sub string and length of substring...

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



回答9:


Here is another clean and simple approach taken from the excellent online course Design of Computer Programs by P. Norvig. It iterates over all characters in the string and attempts to "grow" the string to both left and right.

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)



回答10:


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)



回答11:


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}

('stresseddesserts', 16)




回答12:


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



回答13:


I have to agree the solution may seem to complicated, i think the best solution, to find the largest palindrome in a subsequence, (considering characters in between for example in 'character' the largest palindrome should be carac) is:

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

Where a is an array, this solution uses recursion, and dynamic programming




回答14:


Use a nested loop:

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


来源:https://stackoverflow.com/questions/17217473/python-search-longest-palindromes-within-a-word-and-palindromes-within-a-word-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!