将电话号码编码为单词和搜索字典

时间:2015-05-12 13:10:49

标签: java encoding

我有一项任务。我试过搜索堆栈溢出。

我需要阅读一个充满电话号码的文本文件。这部分我知道该怎么做。

接下来,我需要根据以下编码将电话号码转换为所有可能的单词排列:

E | J N Q | R W X | D S Y | F T | A M | C I V | B K U | L O P | G H Z

e | j n q | r w x | d s y | f t | a m | c i v | b k u | l o p | g h z

0 |   1   |   2   |   3   |  4  |  5  |   6   |   7   |   8   |   9

并根据我要阅读的字典文件检查它们。 (阅读部分我已经知道该怎么做了)

有人可以建议一个好的算法来编码电话号码和检查字典吗?

到目前为止我尝试的所有内容都抛出了OutOfMemory异常,并且赋值指定不一定是这种情况。

1 个答案:

答案 0 :(得分:0)

这是:

static char[][] letters = {"Ee".toCharArray(),      // 0
                           "JNQjnq".toCharArray(),  // 1
                           "RWXrwx".toCharArray()   // 2
                           //.... add remaining
                          };

static Set<String> words = new HashSet<>(Arrays.asList(
                           "Stack", 
                           "Overflow", 
                           "foo", 
                           "bar" 
                           //... add other words
                           ));

// main method
public void generateAndCheckAll(String number) {
    int[] num = new int[number.length()];         // store number as digits
    int[] ind = new int[number.length()];         // store letter indices
    int i = 0;
    for (char c : number.toCharArray()) {         // convert String to int array
        num[i++] = c - '0';
    }
    do {
        String word = generateWord(num, ind);
        System.out.println(word + (words.contains(word) ? " is contained" : " is not contained"));
    } while (next(num, ind));
}


// generate word by number array and index array
public String generateWord(int[] num, int[] ind) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < ind.length; i++) 
        sb.append(letters[num[i]][ind[i]]);
    return sb.toString();
}


// switch index array to next
public boolean next(int[] num, int[] ind) {
    int i = ind.length - 1;
    while (i >= 0 && ind[i] == letters[num[i]].length - 1) // search for the index that can be incremented
        i--;
    if (i < 0)
        return false;
    ind[i]++;                                              // increment such index
    for (int j = i + 1; j < num.length; j++)               // change remaining indices to 0
        ind[j] = 0;
    return true;
}

这里的主要思想是在每次迭代时存储字母索引数组,并根据它生成一个新单词。例如,对于数字201和索引数组[0, 0, 5],将生成单词REq:数字2的第0个字母,数字{{1的第0个字母数字0的第5个字母和第5个字母。

然后在字典中查找该单词,并将索引数组切换到下一个。从最后扫描我们搜索可以递增的索引(这样就不会溢出给定位置的数字的字母数):我们不能增加&#34; 5&#34; (因为数字1只有6个字母),但我们可以增加&#34; 0&#34;。因此,索引数组更改为1,并且一次又一次地重复所有索引,直到所有索引都被允许为最大值。

要了解它的工作原理,请按步骤模式调试此代码。它很容易理解,并将相同的想法应用于许多其他类似的任务。

顺便说一下,这不是最有效的方法,因为字典大小(我认为10-100K)很可能小于组合计数(对于10位数字,大约为60M)。如果您真的不需要生成所有组合,您可以执行字典准备:

  1. 为词典中的每个单词生成一个数字,

  2. 将每个生成的数字映射到相应的单词(单词),并在哈希集合中收集这些映射。

  3. 然后,对于您收到的号码,您只需查看给定号码是否存在单词(单词)。这种方法需要较长的准备阶段和更大的空间,但查找速度显着提高。