我正在研究预测文本解决方案,并根据特定字符串的输入从Trie中检索所有单词,即“at”将使用“at”形成的所有单词作为前缀。我现在遇到的问题是,我们也应该通过按下移动电话上的这两个按钮,按钮2和按钮8来返回所有其他可能性,这也会形成与“au,av,bt,bu”形成的单词。 ,bv,ct,cu,cv“(其中大部分都没有任何实际的词语。
任何人都可以建议一个解决方案以及如何计算不同的排列吗? (目前,我正在提示用户输入前缀(现在不使用GUI)
答案 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
欢迎来到真正的编码:)