我正在寻找最佳方法来搜索一串字母字符,以查找字符串末尾最长的字典单词。
示例:对于字符串qbehugejackhammer
,结果应为jackhammer
而不是hammer
。
有效地执行此操作的一种方法是将相反的单词存储在索引表中,并一次迭代一个字母,直到它不再匹配任何内容:
SELECT word FROM dictionary WHERE word LIKE 'remmahkca%';
SELECT word FROM dictionary WHERE word LIKE 'remmahkcaj%'; # last match
SELECT word FROM dictionary WHERE word LIKE 'remmahkcaje%';
看起来和感觉就像一个黑客,很可能不是最佳解决方案。有没有更快和/或更好的方法来做到这一点?我选择的工具是PHP和MySQL,但如果其他语言或DBMS更适合我的需求,我会全力以赴。
答案 0 :(得分:4)
这可能听起来有点邪恶,但你可能会通过将字典加载到字典树形状的数组中来获得最佳性能,但是以反向字顺序,例如:
array(
'r' => array(
'u' => array(), // -- words ending in 'ur' would end up in here
'a' => array(), // -- words ending in 'ar' would end up here
'e' => array( // -- words ending in 'er' would end up in here
'm' => array(
'm' => array(
// -- jackhammer will be kept further up here
然后寻找。
$reverseWord = ""; // -- Incoming 'word' string goes here, in reverse.
$dictionary = [structure above];
$dictionaryPosition = $dictionary;
$dictionaryHistory = "";
for( $i = 0, $l = strlen($reverseWord); $i < $l; $i++ ) {
$char = $reverseWord[$i];
// -- If this character doesn't exist in this dictionary position, we've reached the end
if( !isset($dictionaryPosition[$char]) )
break;
// -- log this character
$dictionaryHistory = $char . $dictionaryHistory;
// -- Climb up the tree
$dictionaryPosition = $dictionaryPosition[$char];
}
// -- $dictionaryHistory now contains the word you're looking for.
每个数组应包含不超过26个条目(仅假设字母字符),因此您最多只查看每个单个字符的26 * n个查找。即使单词深度为20个字符,也比无数次遍历50k字的列表要好得多。
答案 1 :(得分:4)
您可以从搜索与整个字符串匹配的单词开始,并继续删除字符串开头的字母,直到找到匹配项:
SELECT word FROM dictionary WHERE word = 'qbehugejackhammer'; --no match
SELECT word FROM dictionary WHERE word = 'behugejackhammer'; --no match
SELECT word FROM dictionary WHERE word = 'ehugejackhammer'; --no match
SELECT word FROM dictionary WHERE word = 'hugejackhammer'; --no match
--...
SELECT word FROM dictionary WHERE word = 'jackhammer'; --found it!
答案 2 :(得分:3)
一个快速的hacky答案:将你的字典加载到map
或任何PHP等效数据结构(英语词典只有~50k字,很容易适应RAM v,地图更快,更快查询比DB调用)。然后一次迭代1个字符,针对地图测试每个子字符串,直到找到匹配为止。
根据字符串的长度,你可以通过首先检查字典中最长的单词(你可以在字典加载期间得到这个)并开始适当的距离来优化。我敢肯定还有其他类似的优化你也可以雇用(最开始的角色等)
编辑:“地图”应为“设置”。
答案 3 :(得分:2)
将字典加载到PHP数组中。对于每个输入词,请按照下面的说明在连续较小的子串上使用in_array
(link),直到找到匹配为止。
例如,请考虑您的输入qbehugejackhammer
。首先,搜索数组qbehugejackhammer
,然后搜索behugejackhammer
,然后搜索ehugejackhammer
,依此类推,直至找到匹配项。您可以在找到第一场比赛后立即停止。