Algorithm 字谜词分组算法

Algorithm 字谜词分组算法,algorithm,anagram,data-processing,Algorithm,Anagram,Data Processing,给定一组单词,我们需要找到字谜单词,并使用最佳算法单独显示每个类别 输入: man car kile arc none like 输出: man car arc kile like none ['car', 'arc'] ['kile', 'like'] ['none'] ['man'] 我现在开发的最佳解决方案是基于哈希表,但我正在考虑将字谜字转换为整数值的公式 示例:man=>'m'+'a'+'n',但这不会给出唯一的值 有什么建议吗 请参阅C#中的以下代码: string line

给定一组单词,我们需要找到字谜单词,并使用最佳算法单独显示每个类别

输入:

man car kile arc none like
输出:

man
car arc
kile like
none
['car', 'arc']
['kile', 'like']
['none']
['man']
我现在开发的最佳解决方案是基于哈希表,但我正在考虑将字谜字转换为整数值的公式

示例:man=>'m'+'a'+'n',但这不会给出唯一的值

有什么建议吗


请参阅C#中的以下代码:

string line=Console.ReadLine();
string[]words=line.Split(“”);
int[]数字=GetUniqueInts(字);
for(int i=0;i

问题是如何开发
GetUniqueInts(string[])
方法。

我认为没有什么比使用自定义哈希函数的哈希表更好的了(在对单词进行哈希运算之前,它会对字母进行排序)


字母的总和永远不会起作用,因为你不能真正使“ac”和“bb”有所不同。

你需要大整数(实际上是一个位向量),但下面的方法可能会起作用

第一次出现的每个字母都会被分配该字母的位号,第二次出现的字母会被分配该字母的位号+26

比如说

a#1=1 b#1=2 c#1=4 a#2=2^26 b#2=2^27

然后,您可以将这些值相加,根据单词的字母得到单词的唯一值

您对单词值的存储要求如下:

n*26位


其中n是任何重复字母的最大出现次数。

请不要使用自定义哈希函数。在任何平台上使用普通字符串哈希函数。重要的是要使哈希表的键具有“排序单词”的概念,即单词按字母排序,因此“car”=>“acr”。所有字谜都将具有相同的“排序单词”

只需要从“排序单词”到“排序单词的单词列表”进行散列。在LINQ中,这非常简单:

using System;
using System.Collections.Generic;
using System.Linq;

class FindAnagrams
{
    static void Main(string[] args)
    {
        var lookup = args.ToLookup(word => SortLetters(word));

        foreach (var entry in lookup)
        {
            foreach (var word in entry)
            {
                Console.Write(word);
                Console.Write(" ");
            }
            Console.WriteLine();
        }
    }

    static string SortLetters(string original)
    {
        char[] letters = original.ToCharArray();
        Array.Sort(letters);
        return new string(letters);
    }
}
样本使用:

c:\Users\Jon\Test>FindAnagrams.exe man car kile arc none like
man
car arc
kile like
none

giggles的Python版本:

from collections import defaultdict
res = defaultdict(list)
L = "car, acr, bat, tab, get, cat".split(", ")

for w in L:
    res["".join(sorted(w))].append(w)

print(res.values())

我以前用一个简单的字母计数数组实现过这一点,例如:

unsigned char letter_frequency[26];
然后将其与每个单词一起存储在数据库表中。具有相同字母频率“signature”的单词是字谜,然后一个简单的SQL查询直接返回单词的所有字谜

通过对一本非常大的字典进行一些实验,我发现任何字母的频率都不会超过9,因此“签名”可以表示为数字0..9的字符串(通过将字节压缩为十六进制,可以很容易地将大小减半,通过对数字进行二进制编码,可以进一步减小大小,但到目前为止,我没有对此进行任何处理)

下面是一个ruby函数,用于计算给定单词的签名并将其存储到哈希中,同时丢弃重复项。我稍后将根据哈希构建一个SQL表:

def processword(word, downcase)
  word.chomp!
  word.squeeze!(" ") 
  word.chomp!(" ")
  if (downcase)
    word.downcase!
  end
  if ($dict[word]==nil) 
    stdword=word.downcase
    signature=$letters.collect {|letter| stdword.count(letter)}
    signature.each do |cnt|
      if (cnt>9)
        puts "Signature overflow:#{word}|#{signature}|#{cnt}"
      end
    end
    $dict[word]=[$wordid,signature]
    $wordid=$wordid+1
  end
end

我采用了哥德尔启发的方案:

将素数p_1到p_26分配给字母(以任何顺序,但为了获得较小的散列值,最好将普通字母分配为较小的素数)

建立单词中字母的柱状图

然后散列值是每个字母的相关素数乘以其频率的幂的乘积。这为每个字谜提供了一个唯一的值

Python代码:

primes = [2, 41, 37, 47, 3, 67, 71, 23, 5, 101, 61, 17, 19, 13, 31, 43, 97, 29, 11, 7, 73, 83, 79, 89, 59, 53]


def get_frequency_map(word):
    map = {}

    for letter in word:
        map[letter] = map.get(letter, 0) + 1

    return map


def hash(word):
    map = get_frequency_map(word)
    product = 1
    for letter in map.iterkeys():
        product = product * primes[ord(letter)-97] ** map.get(letter, 0)
    return product
line = "man car kile arc none like"
hmap = {}
for w in line.split():
  ws = ''.join(sorted(w))
  try:
    hmap[ws].append(w)
  except KeyError:
    hmap[ws] = [w]

for i in hmap:
   print hmap[i]

这巧妙地将查找子数组的棘手问题转化为分解大数的(也被认为是棘手的)问题…

为字母a-z指定一个唯一的素数

迭代单词数组,根据每个单词中的字母创建素数乘积。
将该产品与相应的单词一起存储在单词列表中

按产品升序对数组排序


迭代数组,在每次产品更改时进行一次哈希运算。

在C中,我刚刚实现了以下哈希运算,它基本上对字典中的单词是否包含特定字母进行26位位位掩码运算。因此,所有的字谜都有相同的哈希运算。哈希运算不考虑重复的字母,因此会有一些额外的重载,但它仍然比我的perl实现快

#define BUCKETS 49999

struct bucket {
    char *word;
    struct bucket *next;
};

static struct bucket hash_table[BUCKETS];

static unsigned int hash_word(char *word)
{
    char *p = word;
    unsigned int hash = 0;

    while (*p) {
        if (*p < 97 || *p > 122) {
            return 0;
        }
        hash |= 2 << (*p - 97);
        *p++;
    }

    return hash % BUCKETS;
}
#定义bucket 49999
结构桶{
字符*字;
结构桶*next;
};
静态结构桶散列_表[桶];
静态无符号整数散列字(字符*字)
{
char*p=单词;
无符号整数散列=0;
而(*p){
如果(*p<97 |*p>122){
返回0;
}

hash |=2我将根据示例单词和其他我不关心的字母表生成hasmap

例如,如果单词是“car” 我的哈希表如下所示: a、 0 b、 马克斯 c、 一, d、 马克斯 e、 马克斯 ... .. r、 二, . 因此,任何大于3的人都会认为不匹配

(更多调整…) 我的比较方法将比较散列计算本身中的散列总数。一旦能够识别出单词不相等,它就不会继续

public static HashMap<String, Integer> getHashMap(String word) {
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        String[] chars = word.split("");
        int index = 0;
        for (String c : chars) {
            map.put(c, index);
            index++;
        }
        return map;
    }

    public static int alphaHash(String word, int base,
            HashMap<String, Integer> map) {
        String[] chars = word.split("");
        int result = 0;
        for (String c : chars) {
            if (c.length() <= 0 || c.equals(null)) {
                continue;
            }
            int index = 0;
            if (map.containsKey(c)) {
                index = map.get(c);
            } else {
                index = Integer.MAX_VALUE;
            }
            result += index;
            if (result > base) {
                return result;
            }
        }
        return result;
    }
publicstatichashmap getHashMap(字符串字){
HashMap=newHashMap();
字符串[]字符=word.split(“”);
int指数=0;
for(字符串c:chars){
map.put(c,索引);
索引++;
}
返回图;
}
公共静态int-alphaHash(字符串字、int-base、,
HashMap(地图){
字符串[]字符=word.split(“”);
int结果=0;
for(字符串c:chars){
if(c.长度()基){
返回结果;
}
}
返回结果;
}
主要方法

  HashMap<String, Integer> map = getHashMap(sample);
        int sampleHash = alphaHash(sample, Integer.MAX_VALUE, map);
        for (String s : args) {
                if (sampleHash == alphaHash(s, sampleHash, map)) {
                    System.out.print(s + " ");
                }
            }
HashMap-map=getHashMap(示例);
int sampleHash=alphaHash(sample,Integer.MAX_值,map);
for(字符串s:args){
if(sampleHash==alphaHash(s,sampleHash,map)){
系统输出打印(s+“”);
}
}

我不会使用哈希,因为它
var words = 'cat act mac tac ten cam net'.split(' '),
    hashMap = {};

words.forEach(function(w){
    w = w.split('').sort().join('');
    hashMap[w] = (hashMap[w]|0) + 1;
});

function print(obj,key){ 
    console.log(key, obj[key]);
}

Object.keys(hashMap).forEach(print.bind(null,hashMap))
def check_permutation_group(word_list):
    result = {}

    for word in word_list:
        hash_arr_for_word = [0] * 128  # assuming standard ascii

        for char in word:
            char_int = ord(char)
            hash_arr_for_word[char_int] += 1

        hash_for_word = ''.join(str(item) for item in hash_arr_for_word)

        if not result.get(hash_for_word, None):
            result[str(hash_for_word)] = [word]
        else:
            result[str(hash_for_word)] += [word]

return list(result.values())
line = "man car kile arc none like"
hmap = {}
for w in line.split():
  ws = ''.join(sorted(w))
  try:
    hmap[ws].append(w)
  except KeyError:
    hmap[ws] = [w]

for i in hmap:
   print hmap[i]
['car', 'arc']
['kile', 'like']
['none']
['man']