给出
一个充满单词{in, july, den, dentist, best, ...}
的词典,其中有一些C ++ API可以访问它:boolean findWord(string word)
或string getNextWord(void)
来迭代它,
一些没有空格的输入字符串,例如:bestdentistinjuly
...
输出
best dentist in july is...
(基本上用给定字典的空格分隔非空格字符串)解决它的最佳算法是什么?
一个微妙但重要的问题是,是否有任何奇特的方法来解决无法到达的死胡同问题。例如,den
和dentist
都是有效的词来剖析其余的字符串,其中一个可能只是一个死胡同。
对我而言,这似乎是一个贪婪的问题或动态编程可以解决的问题。
答案 0 :(得分:2)
使用Trie存储字典。您可以在How to create a trie in c#
看到一个简单的实现(C#)您需要进行搜索,因为在考虑整个输入字符串之前,您不知道自己是否在正确的轨道上。你需要迭代输入字符串,同时下降到trie中。当你到达特里的终端节点时,你的搜索过程中有一个分支:你需要将它视为单词的结尾并将其视为较长单词的第一部分。
答案 1 :(得分:2)
您可以创建一种词树:
你可以通过没有空格的字符串。一旦你在列表中找到一个单词,你就可以添加一个空格并继续...直到你无法继续前进。
然后你回到上一个单词并尝试添加新单词,你可以创建一个单词,如果你可以从他们继续。
你试试这个,直到你尝试了所有可能性。
如果你回到起始单词并且找不到任何解决方案=>没有溶胶
这是算法(我的伪代码语法不好,但你可以得到一般的想法。我相信你必须纠正一点):
TreeWordResult //Tree that keeps the results in memory
Go through the InputString:
If you find a word in the InputDictionnary
Then add this word to the last node of the treeWordResult
Otherwise:
while (No word found):
go back in the treeWordResult
try to find word in InputDictionnary different from the one before (on the other node)
endwhile
if no word found:
return NO SOLUTION
otherwise:
continue going through word
endif
endif
return Leaf
算法在你找不到溶胶时结束,或当你在“叶子”(你穿过整个字符串)时结束
以下是使用您的示例的插图:
希望我的解释清楚。
答案 2 :(得分:1)
这个问题基本上就像匹配表单的正则表达式一样:
(in|july|den|dentis|best|...)*
因此可以使用任何正则表达式算法。您应该选择哪个取决于字典的大小和输入的长度。你应该从这里开始:http://en.wikipedia.org/wiki/Regular_expression#Implementations_and_running_times
答案 3 :(得分:1)
我认为如果你能让findWord
方法为'not-a-word'和'no-words-starting-with-this-prefix'返回不同的值,你可以加快速度。如果字典存储为trie,这将很容易。
原因是 如果你在@Ricky Bobby的答案中检查单词,在找到'best'之后,你仍然需要检查'bestd'和'bestde'等等一直到字符串的结尾。但是,如果检查'bestd'返回'no-more-words',那么你已经完成了一大堆搜索。
答案 4 :(得分:0)
目前尚不清楚原始帖子究竟要解决什么问题。我猜@Figo正在寻找类似于字符串匹配算法的东西。
答案 5 :(得分:0)
也许有多个有效的解决方案来分隔输入字符串。您可以使用backtracking algorithm找到一个或所有有效的解决方案。在两个或多个单词的位置,例如“den”,“牙医”是可能的,算法应首先尝试较长的单词。
当然字典应该存储在Trie中,以便快速找到匹配的单词。
在下面的ascii图像中,首先会在Depth-first search中检查左侧分支,它更喜欢较长的单词。在算法使用单词“den”查看右侧分支之前,可以找到解决方案。
Best
/ \
dentist den
/
in
/
july