簡體   English   中英

在字符串python中查找最長的唯一子字符串

[英]Find longest unique substring in string python

我正在嘗試尋找不包含重復字符的字符串的最長子字符串的古老問題(周圍有很多版本)。 我不知道為什么我的嘗試不能正常工作:

def findLongest(inputStr):
    resultSet = []
    substr = []

    for c in inputStr:
        print ("c: ", c)
        if substr == []:
            substr.append([c])
            continue

        print(substr)
        for str in substr:
            print ("c: ",c," - str: ",str,"\n")
            if c in str:
                resultSet.append(str)
                substr.remove(str)
            else:
                str.append(c)
        substr.append([c])



    print("Result set:")
    print(resultSet)
    return max(resultSet, key=len)

print (findLongest("pwwkewambb"))

當我的輸出到達第二個“w”時,它不會迭代所有 substr 元素。 我想我做了一些愚蠢的事情,但我看不到它是什么,所以一些指導將不勝感激! 我覺得我要踢自己的答案......

我的輸出的開頭:

c:  p
c:  w
[['p']]
c:  w  - str:  ['p']

c:  w
[['p', 'w'], ['w']]
c:  w  - str:  ['p', 'w'] # I expect the next line to say c: w - str: ['w']

c:  k
[['w'], ['w']] # it is like the w was ignored as it is here
c:  k  - str:  ['w']

c:  k  - str:  ['w']
...

編輯:

我用

for idx, str in enumerate(substr):
    print ("c: ",c," - str: ",str,"\n")
    if c in str:
        resultSet.append(str)
        substr[idx] = []
    else:
        str.append(c)

並產生正確的結果。 唯一的事情是空元素數組被設置為下一個字符。 這似乎有點毫無意義; 必須有更好的方法。

我的預期輸出是kewamb

例如

c:  p
c:  w
[['p']]
c:  w  - str:  ['p']

c:  w
[['p', 'w'], ['w']]
c:  w  - str:  ['p', 'w']

c:  w  - str:  ['w']

c:  k
[[], [], ['w']]
c:  k  - str:  []

c:  k  - str:  []

c:  k  - str:  ['w']

c:  e
[['k'], ['k'], ['w', 'k'], ['k']]
c:  e  - str:  ['k']

c:  e  - str:  ['k']

c:  e  - str:  ['w', 'k']

c:  e  - str:  ['k']
...

不確定您的嘗試有什么問題,但它很復雜並且在:

    for str in substr:
        print ("c: ",c," - str: ",str,"\n")
        if c in str:
            resultSet.append(str)
            substr.remove(str)

您在迭代列表時從列表中刪除元素:不要這樣做,它會產生意想不到的結果。

無論如何,我的解決方案,不確定它是否直觀,但它可能更簡單和更短:

  • 用遞增的索引對字符串進行切片
  • 對於每個切片,創建一個set並存儲字母,直到到達字符串的末尾或一個字母已經在set 您的索引是最大長度
  • 為每次迭代計算此長度的最大值並存儲相應的字符串

代碼:

def findLongest(s):
    maxlen = 0
    longest = ""
    for i in range(0,len(s)):
        subs = s[i:]
        chars = set()
        for j,c in enumerate(subs):
            if c in chars:
                break
            else:
                chars.add(c)
        else:
            # add 1 when end of string is reached (no break)
            # handles the case where the longest string is at the end
            j+=1
        if j>maxlen:
            maxlen=j
            longest=s[i:i+j]
    return longest

print(findLongest("pwwkewambb"))

結果:

kewamb

編輯,@seymour 對錯誤回復的評論:

def find_longest(s):
    _longest = set()
    def longest(x):
         if x in _longest:
             _longest.clear()
             return False
         _longest.add(x)
         return True
    return ''.join(max((list(g) for _, g in groupby(s, key=longest)), key=len))

並測試:

In [101]: assert find_longest('pwwkewambb') == 'kewamb'

In [102]: assert find_longest('abcabcbb') == 'abc'

In [103]: assert find_longest('abczxyabczxya') == 'abczxy'

舊答案:

from itertools import groupby

s = set() ## for mutable access

''.join(max((list(g) for _, g in groupby('pwwkewambb', key=lambda x: not ((s and x == s.pop()) or s.add(x)))), key=len))
'kewamb'

groupby返回一個基於key參數中提供的函數分組的迭代器,默認情況下為lambda x: x 我們通過使用可變結構而不是默認值來利用一些狀態(如果使用普通函數,這可以通過更直觀的方式完成)

lambda x: not ((s and x == s.pop()) or s.add(x))

這里發生的事情是因為我無法在 lambda 中重新分配全局分配(我再次可以這樣做,使用適當的函數),我剛剛創建了一個可以添加/刪除的全局可變結構。 關鍵(沒有雙關語)是我只保留我需要的元素,方法是使用短路根據需要添加/刪除項目。

maxlen是不言自明的,以獲得groupby生成的最長列表

另一個沒有可變全局結構業務的版本:

def longest(x):
     if hasattr(longest, 'last'):
         result = not (longest.last == x)
         longest.last = x
         return result
     longest.last = x
     return True


''.join(max((list(g) for _, g in groupby('pwwkewambb', key=longest)), key=len))
'kewamb'

取決於你對重復字符的定義:如果你的意思是連續的,那么批准的解決方案是光滑的,但不是出現多次的字符(例如: pwwkewabmb -> 'kewabmb' )。

這是我想出的(Python 2):

def longest(word):
    begin = 0
    end = 0
    longest = (0,0)
    for i in xrange(len(word)):
        try:
            j = word.index(word[i],begin,end)
            # longest?
            if end-begin >= longest[1]-longest[0]:
                longest = (begin,end)
            begin = j+1
            if begin==end:
                end += 1
        except:
            end = i+1
    end=i+1
    if end-begin >= longest[1]-longest[0]:
        longest = (begin,end)
    return word[slice(*longest)]

因此

>>> print longest('pwwkewabmb')
kewabm
>>> print longest('pwwkewambb')
kewamb
>>> print longest('bbbb')
b

我的 2 美分:

from collections import Counter

def longest_unique_substr(s: str) -> str:

    # get all substr-ings from s, starting with the longest one
    for substr_len in range(len(s), 0, -1):
        for substr_start_index in range(0, len(s) - substr_len + 1):
            substr = s[substr_start_index : substr_start_index + substr_len]

            # check if all substr characters are unique
            c = Counter(substr)
            if all(v == 1 for v in c.values()):
                return substr

    # ensure empty string input returns ""
    return ""

運行:

In : longest_unique_substr('pwwkewambb')
Out: 'kewamb'
s=input()
ma=0
n=len(s)
l=[]
a=[]
d={}
st=0;i=0
while i<n:
    if s[i] not in d:
        d[s[i]]=i
        l.append(s[i])
    else:
        t=d[s[i]]
        d[s[i]]=i
        s=s[t+1:]
        d={}
        n=len(s)
        if len(l)>=3:
            a.append(l)
            ma=max(ma,len(l))
        l=[];i=-1
    i=i+1
if len(l)!=0 and len(l)>=3:
    a.append(l)
    ma=max(ma,len(l))
if len(a)==0:
    print("-1")
else:
    for i in a:
        if len(i)==ma:
            for j in i:
                print(j,end="")
            break

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM