【问题标题】:How to find anagrams using 3 words in a text having a list of words?如何在具有单词列表的文本中使用 3 个单词查找字谜?
【发布时间】:2019-11-21 01:41:40
【问题描述】:

我有一个文本和一个 60k 单词的列表。 我需要使用 3 个单词(按字母顺序排列)从单词列表中找到文本的字谜,并且该函数应该返回 3 个单词的元组,这些单词构成给定文本的字谜。 注意:我必须忽略文本中的大写字母和空格。

我开发了查找包含在文本中的单词列表中的所有单词的功能。 但我不知道如何结束查找字谜。

   def es3(words_list, text):
        text=text.replace(" ","")
        for x in text:
        text=text.replace(x,x.lower())

        result=[]
        cont=0
        for x in words_list:
            if len(x)>=2:
                for c in x:
                    if c in text:
                        cont+=1
                        if cont==len(x):
                            result.append(x)
            cont=0


           Examples:
          text =   "Andrea Sterbini"  -> anagram= ('treni', 'sia', 'brande')
            sorted(andreasterbini)==sorted(treni+sia+brande) 


            "Angelo Monti"          -> ('toni', 'nego', 'mal')
            "Angelo Spognardi"      -> ('sragion', 'pend', 'lago')
            "Ha da veni Baffone"    -> ('video', 'beh', 'affanna')

【问题讨论】:

  • 没关系,我没有正确阅读问题 - 抱歉 - 忘记这条评论
  • 用单词列表更新问题
  • 我需要从构建文本字谜的 words_list 中找到 3 个单词。
  • 单词列表是60k单词的列表..
  • 好的,在示例中,“Andrea Sterbini”是文本,对吧?

标签: python string list


【解决方案1】:

简单的算法是:

  • 获取每三个单词,并将项目 (sorted letters of the three words, triplet) 添加到多映射(每个键可以接受多个值的映射:在 Python 中,正则映射 key -> [values])。
  • 对搜索文本的字母进行排序,并在多图中输出相关值。

问题是多图的构造具有O(N^3) 的时间和空间复杂度。如果 N = 60,000,则您有 216,000 亿个操作和值。太多了!

让我们尝试减少这种情况。让我重述这个问题:给定一个序列,找到三个子序列: 1. 不重叠并覆盖该序列; 2. 在给定的集合中。查看您的第一个示例:“Angelo Monti”-> ('toni', 'nego', 'mal')

sequence    a e g i l m n n o o t
subseq1           i     n   o   t
subseq2       e g         n   o
subseq3     a       l m

找到覆盖序列的三个非重叠子序列与将一组 n 个元素划分为 k 个组是相同的问题。复杂度称为S(n, k),以1/2 (n k) k^(n-k) 为界。因此,找到 k 个组中 n 个元素的所有分区具有O(n^k * k^(n-k)) 复杂度。

让我们尝试在 Python 中实现它:

def partitions(S, k):
    if len(S) < k: # can't partition if there are not enough elements
        raise ValueError()
    elif k == 1:
        yield tuple([S]) # one group: return the set
    elif len(S) == k:
        yield tuple(map(list, S)) # ([e1], ..., [e[n]])
    else:
        e, *M = S # extract the first element
        for p in partitions(M, k-1): # we need k-1 groups because...
            yield ([e], *p) # the first element is a group on itself
        for p in partitions(M, k):
            for i in range(len(p)): # add the first element to every group
                yield tuple(list(p[:i]) + [[e] + p[i]] + list(p[i+1:]))

一个简单的测试:

>>> list(partitions("abcd", 3))
[(['a'], ['b'], ['c', 'd']), (['a'], ['b', 'c'], ['d']), (['a'], ['c'], ['b', 'd']), (['a', 'b'], ['c'], ['d']), (['b'], ['a', 'c'], ['d']), (['b'], ['c'], ['a', 'd'])]

现在,我将使用您在问题中使用的一些单词作为单词列表:

words = "i have a text and a list of words i need to find anagrams of the text from the list of words using words lasts in alphabetic order and the function should return a tuple of the words that build an anagram of the given text note i have to ignore capital letters and spaces that are in the text i have developed the function that finds all the words of the list of words that are contained in the text but i dont know how to end finding the anagrams and some examples treni sia brande toni nego mal sragion pend lago video beh affanna".split(" ")

并构建一个字典 sorted(letters) -&gt; list of words 来检查组

word_by_sorted = {}
for w in words:
    word_by_sorted.setdefault("".join(sorted(w)), set()).add(w)

结果是:

>>> word_by_sorted
{'i': {'i'}, 'aehv': {'have'}, 'a': {'a'}, 'ettx': {'text'}, 'adn': {'and'}, 'ilst': {'list'}, 'fo': {'of'}, 'dorsw': {'words'}, 'deen': {'need'}, 'ot': {'to'}, 'dfin': {'find'}, 'aaagmnrs': {'anagrams'}, 'eht': {'the'}, 'fmor': {'from'}, 'ginsu': {'using'}, 'alsst': {'lasts'}, 'in': {'in'}, 'aabcehilpt': {'alphabetic'}, 'deorr': {'order'}, 'cfinnotu': {'function'}, 'dhlosu': {'should'}, 'enrrtu': {'return'}, 'elptu': {'tuple'}, 'ahtt': {'that'}, 'bdilu': {'build'}, 'an': {'an'}, 'aaagmnr': {'anagram'}, 'eginv': {'given'}, 'enot': {'note'}, 'eginor': {'ignore'}, 'aacilpt': {'capital'}, 'eelrstt': {'letters'}, 'acepss': {'spaces'}, 'aer': {'are'}, 'ddeeelopv': {'developed'}, 'dfins': {'finds'}, 'all': {'all'}, 'acdeinnot': {'contained'}, 'btu': {'but'}, 'dnot': {'dont'}, 'know': {'know'}, 'how': {'how'}, 'den': {'end'}, 'dfgiinn': {'finding'}, 'emos': {'some'}, 'aeelmpsx': {'examples'}, 'einrt': {'treni'}, 'ais': {'sia'}, 'abdenr': {'brande'}, 'inot': {'toni'}, 'egno': {'nego'}, 'alm': {'mal'}, 'aginors': {'sragion'}, 'denp': {'pend'}, 'aglo': {'lago'}, 'deiov': {'video'}, 'beh': {'beh'}, 'aaaffnn': {'affanna'}}

现在,把砖块放在一起:分三组检查text的每个分区,如果三组是列表中单词的字谜,则输出单词:

for p in partitions("angelomonti", 3):
    L = [word_by_sorted.get("".join(sorted(xs)), set()) for xs in p]
    for anagrams in itertools.product(*L):
        print (anagrams)

备注:

  • word_by_sorted.get("".join(sorted(xs)), set()) 在字典中搜索已排序的字母组作为字符串,如果没有匹配则返回单词集空集
  • itertools.product(*L) 创建找到集的笛卡尔积。如果存在空集(不匹配的组),则根据定义,该产品为空。

输出(有重复的原因,尝试查找!):

('nego', 'mal', 'toni')
('mal', 'nego', 'toni')
('mal', 'nego', 'toni')
('mal', 'nego', 'toni')

这里重要的是单词的数量不再是一个问题(在字典中的查找是摊销的O(1)),但是要搜索的文本的长度可能会变成一个。

【讨论】:

    猜你喜欢
    • 2011-09-19
    • 2021-08-27
    • 1970-01-01
    • 2013-09-20
    • 2011-02-07
    • 2015-05-06
    • 2012-09-10
    • 2011-12-15
    • 1970-01-01
    相关资源
    最近更新 更多