通过添加变音符号返回可以从给定字符串生成的所有单词

时间:2014-02-28 10:25:49

标签: java string algorithm sqlite combinatorics

假设有一个基于拉丁语的晦涩字母表,但有很多变音符号(实际上,我使用的字母表是基于西里尔语的,这本身就很混乱,所以我决定使用一个简单的拉丁语例子)

即使设备支持这种语言,输入也很不方便(你需要经常切换布局,使用组合键等),所以我想让用户只能使用“普通”字符进行输入。 o 信件代表 o 本身,然后óö等。

例如,有一个单词“fóobař”。用户只需输入“foobar”,程序就必须返回“fóobař”条目的一些数据。

我这样做:

public static void main(String[] args) {
    HashSet<String> guesses = new HashSet();
    String initial = "foobar";
    generate(initial, 0, guesses);
    System.out.println(guesses);
}

private static void generate(String s, int startFrom, HashSet<String> guesses) {        
    if (startFrom == s.length() - 1) {
        return;
    }
    guesses.add(s);
    for (int i = startFrom; i < s.length(); i++) {
        char[] substitutes = getSubstitutes(s.charAt(i));
        for (char ch : substitutes) {
            String newGuess = replaceCharAt(s, i, ch);
            generate(newGuess, i + 1, guesses);
        }           
    }       
}

private static char[] getSubstitutes(char ch) {
    char[] substitutes;
    switch (ch) {
    case 'o':
        substitutes = new char[] {'ó', 'ö'};
        return substitutes;
    case 'r':
        substitutes = new char[] {'ř'};
        return substitutes;
        default:
            return new char[] {};
    }
}

private static String replaceCharAt(String s, int position, char ch) {      
    return s.substring(0, position) + ch + s.substring(position + 1);
}

也就是说,我递归地生成所有可能的替换:

[foóbar, foobař, fóóbar, foobar, foóbař, fööbař, föóbar,
 föobař, fööbar, föóbař, fóóbař, fóöbař, föobar, fóobar,
 foöbař, foöbar, fóobař, fóöbar]

然后执行具有多个WHERE条件的数据库查询

有没有比尝试所有可能的值更好的方法呢?编写SQLite函数与REGEXP一起使用会更好吗?

1 个答案:

答案 0 :(得分:0)

在数据库方面,创建一个带有单词副本的附加列,但每个字符都转换为其“普通”版本,例如将óö等转换为o

它实际上可能会更好computed column,但它看起来并不像SQLite支持这一点。

然后您可以对输入的文本执行相同的转换,并查询已添加的列以查找转换后的文本。

示例:

Word     NormalizedWord
foobar   foobar
foöbar   foobar
fóóbar   foobar

查询:fóöbar

规范化查询:foobar

然后只需查找NormalizedWordfoobar的行(在这种情况下,这将是以上所有内容)。


上述方法是优化运行时间 - 它允许您向NormalizedWord添加索引,以便快速查找。

为了优化空间使用,您可以只存储单词,并在查找中动态转换,但这需要您查看所有行,无论如何这样做都不允许索引。

通过'即时转换',我的意思是:

SELECT *
FROM Table
WHERE Normalize(Word) = NormalizedInputString