从多个角色生成排列

时间:2010-05-04 14:41:29

标签: java character permutation

我正在研究预测文本解决方案,并根据特定字符串的输入从Trie中检索所有单词,即“at”将使用“at”形成的所有单词作为前缀。我现在遇到的问题是,我们也应该通过按下移动电话上的这两个按钮,按钮2和按钮8来返回所有其他可能性,这也会形成与“au,av,bt,bu”形成的单词。 ,bv,ct,cu,cv“(其中大部分都没有任何实际的词语。

任何人都可以建议一个解决方案以及如何计算不同的排列吗? (目前,我正在提示用户输入前缀(现在不使用GUI)

1 个答案:

答案 0 :(得分:3)

欢迎使用recursivity和combinatorial-explosion等概念:)

由于组合爆炸,你必须对它“聪明”:如果用户想要输入一个合法的20个字母的单词,你的解决方案“挂起”试图愚蠢的数千万种可能性是不可接受的。

所以你应该只在trie至少有一个你的前缀条目时递归。

这是一种生成所有前缀的方法,只有在匹配时才会递归。

在这个例子中,我伪造了一个特里总是说有一个条目。我在五分钟内做到了这一点,所以它肯定可以被美化/简化。

这种解决方案的优势在于,如果用户按下一个,两个,三个,四个或'n'个键,它就可以工作,而无需更改代码。

请注意,当有太多时,您可能不希望添加所有以'x'字母开头的单词。您可以找到最符合您需求的策略(等待更多按键减少候选人或添加最常见的匹配作为候选人等。)

private void append( final String s, final char[][] chars, final Set<String> candidates ) {
        if ( s.length() >= 2 && doesTrieContainAnyWordStartingWith( s ) ) {
            candidates.add( s + "..." ); // TODO: here add all words starting with 's' instead of adding 's'
        }
        if ( doesTrieContainAnyWordStartingWith( s ) && chars.length > 0 ) {
            final char[][] next = new char[chars.length-1][];
            for (int i = 1; i < chars.length; i++) {
                next[i-1] = chars[i];
            }
            // our three recursive calls, one for each possible letter
            // (you'll want to adapt for a 'real' keyboard, where some keys may only correspond to two letters)
            append( s + chars[0][0], next, candidates );
            append( s + chars[0][1], next, candidates );
            append( s + chars[0][2], next, candidates );
        } else {
            // we do nothing, it's our recursive termination condition and
            // we are sure to hit it seen that we're decreasing our 'chars'
            // length at every pass  
        }
    }

    private boolean doesTrieContainAnyWordStartingWith( final String s ) {
        // You obviously have to change this
        return true;
    }

请注意递归调用(仅当存在匹配的前缀时)。

以下是你可以调用它的方法:我伪造用户按'1',然后'2'然后'3'(我在我创建的 chars char [] []数组中伪造了这个):

    public void testFindWords() {
        // Imagine the user pressed 1 then 2 then 3
        final char[][] chars = {
                {'a','b','c'},
                {'d','e','f'},
                {'g','h','i'},
        };
        final Set<String> set = new HashSet<String>();
        append( "", chars, set ); // We enter our recursive method
        for (final String s : set ) {
            System.out.println( "" + s );
        }
        System.out.println( "Set size: " + set.size() );
}

该示例将创建一个包含36个匹配的集合,因为我“伪造”每个前缀都是合法的,并且每个前缀只能导致一个单词(并且当它由至少两个字母组成时我只添加了“单词”)。因此3 * 3 * 3 + 3 * 3,得到36。

您可以尝试使用该代码,但它完全正常工作,但您当然必须对其进行调整。

在我的假例子中(用户按1,2然后按3),它会创建:

cdh...
afi...
adi...
beg...
cf...
adh...
cd...
afg...
adg...
bei...
ceg...
bfi...
cdg...
beh...
aeg...
ce...
aeh...
afh...
bdg...
bdi...
cfh...
ad...
cdi...
ceh...
bfh...
aei...
cfi...
be...
af...
bdh...
bf...
cfg...
bfg...
cei...
ae...
bd...
Set size: 36

欢迎来到真正的编码:)