在字符串末尾查找最长的字典单词

时间:2011-03-23 16:19:37

标签: php mysql optimization string dictionary

我正在寻找最佳方法来搜索一串字母字符,以查找字符串末尾最长的字典单词。

示例:对于字符串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更适合我的需求,我会全力以赴。

4 个答案:

答案 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_arraylink),直到找到匹配为止。

例如,请考虑您的输入qbehugejackhammer。首先,搜索数组qbehugejackhammer,然后搜索behugejackhammer,然后搜索ehugejackhammer,依此类推,直至找到匹配项。您可以在找到第一场比赛后立即停止。