Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 将字符串拆分为字典中的单词_Php_Algorithm_Substring - Fatal编程技术网

Php 将字符串拆分为字典中的单词

Php 将字符串拆分为字典中的单词,php,algorithm,substring,Php,Algorithm,Substring,我正在寻找PHP中最有效的算法来检查字符串是否仅由字典单词组成 例如: thissentencewasmadefromenglishwords thisonecontainsyxxxyxsomegarbagexaatoo pure thisisalsobadxyyyaazzz 输出: thissentencewasmadefromenglishwords pure a、 文本 contains the dictionary words b、 文本 这是一个可以使用以下公式解决的问题: f(

我正在寻找PHP中最有效的算法来检查字符串是否仅由字典单词组成

例如:

thissentencewasmadefromenglishwords
thisonecontainsyxxxyxsomegarbagexaatoo
pure
thisisalsobadxyyyaazzz
输出:

thissentencewasmadefromenglishwords
pure
a、 文本

contains the dictionary words
b、 文本


这是一个可以使用以下公式解决的问题:

f(0) = true
f(i) = OR { f(i-j) AND Dictionary.contais(s.substring(i-j,i) } for each j=1,...,i
首先,将文件加载到字典中,然后对上述公式使用DP解决方案

伪代码是这样的:(希望我没有索引的“off by one”。)


我建议使用递归方法。大概是这样的:

<?php
    $wordsToCheck = array(
        'otherword',
        'word1andother',
        'word1',
        'word1word2',
        'word1word3',
        'word1word2word3'
    );
    $wordList = array(
        'word1',
        'word2',
        'word3'
    );
    $results = array();

    function onlyListedWords($word, $wordList) {
        if (in_array($word, $wordList)) {
            return true;
        } else {
            $length = strlen($word);
            $wordTemp = $word;
            $part = '';
            for ($i=0; $i < $length; $i++) { 
                $part .= $wordTemp[$i];
                if (in_array($part, $wordList)) {
                    if ($i == $length - 1) {
                        return true;
                    } else {
                        $wordTemp = substr($wordTemp, $i + 1);
                        return onlyListedWords($wordTemp, $wordList);
                    }
                }
            }
        }
    }

    foreach ($wordsToCheck as $word) {
        if (onlyListedWords($word, $wordList))
            $results[] = $word;
    }

    var_dump($results);
?>

另一种方法是使用。基本的想法是在你的字典中阅读单词,并从中创建Aho-Corasick树结构。然后,通过搜索函数运行要拆分为单词的每个字符串

这种方法的优点在于,创建树只需一次性成本。然后,您可以将其用于正在测试的所有字符串。搜索函数以O(n)(n是字符串的长度)加上找到的匹配数运行。这真的很有效

搜索函数的输出将是一个字符串匹配列表,告诉您哪些单词在什么位置匹配

维基百科的文章并没有对Aho-Corasick算法给出很好的解释。我更喜欢原稿,它很平易近人。看

例如,给定第一个字符串:

thissentencewasmadefromenglishwords
你会得到(部分):

现在,按位置对匹配列表进行排序。当您从字符串匹配器获得它时,它几乎会被排序,但不是完全排序

一旦列表按位置排序,您要做的第一件事就是确保位置0处存在匹配项。如果没有,则字符串测试失败。如果存在(并且在位置0处可能存在多个匹配项),则获取匹配字符串的长度,并查看该位置是否存在字符串匹配项。加上比赛的长度,看下一个位置是否有比赛,等等

如果要测试的字符串不是很长,那么可以使用类似的蛮力算法。不过,构建一个按位置索引的匹配项哈希映射会更有效。当然,一个特定的职位可能有多个匹配项,所以你必须考虑到这一点。但看看是否有一个位置上的比赛将是非常快的

当然,要实现Aho-Corasick算法需要做一些工作。快速的Google搜索显示有可用的php实现。我不知道他们工作得有多好


在一般情况下,这应该是非常快的。同样,这取决于字符串的长度。但在任何一个位置都有相对较少的比赛,这对你有所帮助。您可能会构造出运行时异常糟糕的字符串,但您可能必须非常努力。再说一次,如果字符串很短,即使是病理病例也不会花费太长的时间。

你真的在寻找最有效的算法吗?或者任何在合理时间内起作用的东西都会起作用吗?你有可以逐字查询的字典吗?您尝试过什么,或者您不知道如何解决问题?您好,任何运行速度超过10-15分钟的都可以。得到了一个包含100000个单词的单词列表,字符串列表大约为50000个。我试图搜索每个字符串中的单词,如果可以用找到的单词生成字符串,那么它就是一个输出字符串。但它不是最快的。它会覆盖像smartestonia(smart+Estania=一个好的点击率或smartest+onia wich是一个坏的点击率)这样有问题的字符串吗?@fobiss是的,当然。这就是DP的重点。这基本上是一种实现穷举搜索的有效方法。我曾尝试用php实现您的pseudo,但效果不好,我认为substring方法可能会令人困惑。在php中,substr使用第三个参数返回字符的长度。第二个参数在pseudo中是什么意思?@CyberCube参数是所需子字符串的开始索引和结束索引。确保指示器中没有“关闭1”错误。这基本上是我提出的DP解决方案的无效解决方案(穷举搜索)。为了提高效率(并且对长度为100的字符串是可行的),您需要引入自上而下(记忆)DP或自下而上DP(我的答案建议使用第二种,自下而上)。如果没有上述改进,您将无法对长度为100的字符串运行它,因为所消耗的时间呈指数级增长。
<?php
    $wordsToCheck = array(
        'otherword',
        'word1andother',
        'word1',
        'word1word2',
        'word1word3',
        'word1word2word3'
    );
    $wordList = array(
        'word1',
        'word2',
        'word3'
    );
    $results = array();

    function onlyListedWords($word, $wordList) {
        if (in_array($word, $wordList)) {
            return true;
        } else {
            $length = strlen($word);
            $wordTemp = $word;
            $part = '';
            for ($i=0; $i < $length; $i++) { 
                $part .= $wordTemp[$i];
                if (in_array($part, $wordList)) {
                    if ($i == $length - 1) {
                        return true;
                    } else {
                        $wordTemp = substr($wordTemp, $i + 1);
                        return onlyListedWords($wordTemp, $wordList);
                    }
                }
            }
        }
    }

    foreach ($wordsToCheck as $word) {
        if (onlyListedWords($word, $wordList))
            $results[] = $word;
    }

    var_dump($results);
?>
thissentencewasmadefromenglishwords
this, 0
his, 1
sent, 4
ten, 7
etc.