微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

字符串列表中的公共子字符串

如何解决字符串列表中的公共子字符串

我在尝试解决给定一些字符串及其长度的问题时遇到问题,您需要找到它们的公共子字符串。我循环遍历列表然后遍历列表中每个单词的部分代码是这样的:

num_of_cases = int(input())
for i in range(1,num_of_cases+1):
    if __name__ == '__main__':
        len_of_str = list(map(int,input().split()))
        len_of_virus = int(input())

    strings = []
    def string(strings,len_of_str):
        len_of_list = len(len_of_str)
        for i in range(1,len_of_list+1):
            strings.append(input())
    
    lst_of_subs = []
    virus_index = []
    def substr(strings,len_of_virus):
        for word in strings:
             for i in range(len(len_of_str)):
                  leng = word[i:len_of_virus]
                  lst_of_subs.append(leng)
                  virus_index.append(i)

    print(string(strings,len_of_str))
    print(substr(strings,len_of_virus))

根据字符串打印以下内容:ananasso、associazione、tassonomia、massone

['anan','nan','an','n','asso','sso','so','o','tass','ass','ss','s','mass','s']

似乎结束索引没有增加,尽管我通过在循环末尾写 len_of_virus += 1 来尝试它。

样本输入:

1
8 12 10 7
4
ananasso
associazione
tassonomia
massone

其中第一个字母是病例数,第二行是字符串的名称,第三行是病毒的长度(公共子字符串),然后是我应该循环遍历的给定字符串。

预期输出

Case #1: 4 0 1 1

其中四个数字是公共子串的起始索引。(我认为打印代码不会关心我们这个特定问题)

我该怎么办?请帮忙!!

解决方法

问题,除了在奇怪的地方定义函数和使用所述函数以不真正鼓励的方式获得副作用外,还在于:

for i in range(len(len_of_str)):
    leng = word[i:len_of_virus]

i 在每次迭代中不断增加,但 len_of_virus 保持不变,因此您正在有效地执行

word[0:4] #when len_of_virus=4
word[1:4]
word[2:4]
word[3:4]
...

这就是 'anan','nan','an','n', 来自第一个词“ananasso”的地方,另一个词也是如此

>>> word="ananasso"
>>> len_of_virus = 4
>>> for i in range(len(word)):
        word[i:len_of_virus]

    
'anan'
'nan'
'an'
'n'
''
''
''
''
>>> 

你可以通过 i 移动上端来修复它,但在另一端留下同样的问题

>>> for i in range(len(word)):
    word[i:len_of_virus+i]

    
'anan'
'nana'
'anas'
'nass'
'asso'
'sso'
'so'
'o'
>>>

所以在范围和问题上做一些简单的调整:

>>> for i in range(len(word)-len_of_virus+1):
        word[i:len_of_virus+i]

    
'anan'
'nana'
'anas'
'nass'
'asso'
>>> 

现在子串部分完成了,剩下的也很简单

>>> def substring(text,size):
        return [text[i:i+size] for i in range(len(text)-size+1)]

>>> def find_common(lst_text,size):
        subs = [set(substring(x,size)) for x in lst_text]
        return set.intersection(*subs)

>>> test="""ananasso
associazione
tassonomia
massone""".split()
>>> find_common(test,4)
{'asso'}
>>> 

要找到列表中所有字符串的公共部分,我们可以使用 set,首先我们将给定单词的所有子字符串放入一个集合中,最后将它们全部相交。

剩下的就是按照自己的喜好打印

>>> virus = find_common(test,4).pop()
>>> print("case 1:",*[x.index(virus) for x in test])
case 1: 4 0 1 1
>>> 
,

首先从最短的字符串中提取给定大小的所有子字符串。然后选择所有字符串中存在的这些子字符串中的第一个。最后输出这个公共子串在每个字符串中的位置:

def commonSubs(strings,size):
    base = min(strings,key=len) # shortest string
    subs = [base[i:i+size] for i in range(len(base)-size+1)] # all substrings
    cs = next(ss for ss in subs if all(ss in s for s in strings)) # first common
    return [s.index(cs) for s in strings] # indexes of common substring

输出:

S = ["ananasso","associazione","tassonomia","massone"]
print(commonSubs(S,4))
[4,1,1]

您也可以使用递归方法:

def commonSubs(strings,size,i=0):
    sub = strings[0][i:i+size]
    if all(sub in s for s in strings):
        return [s.index(sub) for s in strings]
    return commonSubs(strings,i+1)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。