【问题标题】:How to find find anagrams among words, which are given in a file如何在文件中给出的单词中查找字谜
【发布时间】:2011-12-15 08:25:47
【问题描述】:

如何在文件中给出的单词中查找字谜。

我的解决方案:

对它们进行排序,然后查找重复项。

O(n mlgm)。 n:字数,m:字的最大大小

有更好的解决方案吗?

谢谢

【问题讨论】:

  • 这里的n 是什么?我认为您的复杂性表达式中需要两个变量;一个表示单词数,一个表示每个单词的字符数。
  • 你的意思是对每个单词的字符进行排序并比较结果字符串吗?
  • Quantuum Bogosort: en.wikipedia.org/wiki/Bogosort,但除此之外,我猜你在那里找到了一个很好的解决方案。

标签: string algorithm sorting


【解决方案1】:

这是一个没有排序的解决方案: 我想出了一个新的解决方案。它使用算术基本定理。所以这个想法是使用前 26 个素数的数组。然后对于输入单词中的每个字母,我们得到相应的素数 A = 2,B = 3,C = 5,D = 7 ……然后我们计算输入单词的乘积。接下来,我们对字典中的每个单词执行此操作,如果一个单词与我们的输入单词匹配,那么我们将其添加到结果列表中。所有字谜都将具有相同的签名,因为

任何大于 1 的整数要么是素数,要么可以写成 作为素数的唯一乘积(忽略顺序)。

这是代码。我将单词转换为大写,65 是 A 的位置,对应于我的第一个素数:

private int[] PRIMES = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
        37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
        107, 109, 113 };

这是函数:

 private long calculateProduct(char[] letters) {
    long result = 1L;
    for (char c : letters) {
        if (c < 65) {
            return -1;
        }
        int pos = c - 65;
        result *= PRIMES[pos];
    }
    return result;
}

完整的描述在这里: Anagram on dev.vvirlan.com

【讨论】:

  • 太棒了......它肯定是独一无二的和创新的:)
  • 其实你描述的方法可以作为单词的散列函数。创建唯一的哈希作为字典键和单词作为值
  • 不,散列不起作用,因为您不需要每个单词的唯一键。您需要为所有字谜使用相同的密钥(或哈希)。停止,底池和顶必须都具有相同的哈希值......如何实现?我的解决方案提供了答案。
  • 你没有明白我的意思——我的回答是一种增强,而不是你的解决方案的替代品。您的方法是算法(如散列函数),可用于为每个单词创建唯一标识符 - stop/pots/tops 将给出相同的标识符。现在,如果数据集有 100 个项目,并且我想检查第 50 个项目是否是字谜,那么我需要保留之前的 49 个标识符,然后才能进行比较。因此,将标识符保存在另一个哈希表中作为键和单词作为每个键的值列表,以便比较是 O(1)。
  • 我明白了,你是说我们需要使用一些缓存的方法来增强搜索方法吗?但是你不能缓存所有的字典。我的意思是它太大了。
【解决方案2】:

使用在单词排列下不变的散列函数对所有单词进行散列,例如计算每个字母的频率计数并散列该数组。将它们放在哈希表中并查找哈希到相同值的条目(当然,由于哈希表的性质,您仍然需要测试这些冲突是否是实际的字谜)。

这应该在 O(n) 时间内运行,假设您选择了一个好的散列函数并且您的输入集不包含太多的字谜(在最坏的情况下,如果每个单词都是其他单词的字谜,这会在O(n2) 次)。

【讨论】:

    【解决方案3】:
    # list of words
    words = ["ROOPA","TABU","OOPAR","BUTA","BUAT" , "PAROO","Soudipta",
            "Kheyali Park", "Tollygaunge", "AROOP","Love","AOORP",
             "Protijayi","Paikpara","dipSouta","Shyambazaar",
            "jayiProti", "North Calcutta", "Sovabazaar"]
    
    #Method 1
    A = [''.join(sorted(word)) for word in words]
    
    dict ={}
    
    for indexofsamewords,samewords in enumerate(A):
        dict.setdefault(samewords, []).append(indexofsamewords)
        
    print(dict)
    #{'AOOPR': [0, 2, 5, 9, 11], 'ABTU': [1, 3, 4], 'Sadioptu': [6, 14], ' KPaaehiklry': [7], 'Taeggllnouy': [8], 'Leov': [10], 'Paiijorty': [12, 16], 'Paaaikpr': [13], 'Saaaabhmryz': [15], ' CNaachlortttu': [17], 'Saaaaborvz': [18]}
    
    for index in dict.values(): 
        print( [words[i] for i in index ] )
        
    

    输出:

    ['ROOPA', 'OOPAR', 'PAROO', 'AROOP', 'AOORP']
    ['TABU', 'BUTA', 'BUAT']
    ['Soudipta', 'dipSouta']
    ['Kheyali Park']
    ['Tollygaunge']
    ['Love']
    ['Protijayi', 'jayiProti']
    ['Paikpara']
    ['Shyambazaar']
    ['North Calcutta']
    ['Sovabazaar']
    

    【讨论】:

      【解决方案4】:

      更好的解决方案:假设单词的平均长度较小。如有必要,请向您当地的语言专家索取参考资料。然后应用您想到的算法;如果它是我的想法,它会在数学上具有预期的线性时间性能,以字数表示

      【讨论】:

        【解决方案5】:

        这是一个老话题,但我会发布它以防有人偶然发现:

        我已经描述了在谷歌电子表格中完成的过程(也可以在 excel 中完成)。这是一个非常简单的方法。

        http://imgur.com/a/eqwZ6

        基本上,您将列出字符串并将每个字符串分解为字母。你拿走每个“信件包”并按字母顺序对它们进行排序。重新组合成单​​词,但字母按字母顺序排序。对组装好的“单词”进行排序 - 所有字谜都彼此相邻。制作一个简单的公式来标记字谜。

        【讨论】:

          猜你喜欢
          • 2015-05-06
          • 2012-09-10
          • 2013-09-20
          • 1970-01-01
          • 2011-09-19
          • 2011-02-07
          • 2019-06-25
          • 2019-11-21
          • 1970-01-01
          相关资源
          最近更新 更多