找到仍然可识别的单词,其中一些(最多)字符被另一个字符替换

时间:2018-05-28 20:04:33

标签: php memory memory-management

我已经组装了这个小算法,能够创建所有可能的字母和下划线的列表(茶 - > te_ - > t_a - > _ea - > t__ - > .. 。) 一组单词。然后它比较安排并找到独特的(tee& tea => [tea,tee,t_a,t_e,_ea,_ee,__ a,__ e])。我的问题是,对于较大的单词,程序使用太多的内存(我毕竟创建了一个包含所有可能组合的树)。我在考虑创造每个单词'树同时然后在重复的过程中解除重复,但我不确定如何做到这一点。

这是我的代码部分,内存分配很差,其中包含" tea"和" tee"作为测试用例:

$word1 = "tea tee";
$word1 = preg_split('/ +/', $word1);
$word1 = array2d($word1);
$word1 = get_multipleCombinations($word1);
$word1 = compare_combinations($word1);

foreach($word1 as $key1=>$level1){
    foreach($level1 as $key2=>$level2){
        foreach($level2 as $key3=>$level3){
            echo $word1[$key1][$key2][$key3];       
    }

    echo " ";
}

}

function array2d($words){
    $count = count($words);

    for ($i = 0; $i <= $count-1; $i++) {

        $words[$i] = str_split($words[$i]);
    }
    for ($i = 0; $i <= $count-1; $i++) {

        for ($j = 0; $j <= count($words[$i])-1; $j++){

            $words[$i][$j] = array("_", $words[$i][$j]);
        }
    }
    return $words;
}

function get_combinations($arrays) {
    $result = array(array());
    foreach ($arrays as $key => $values) {
        $temp = array();
        foreach ($result as $results) {
            foreach ($values as $value) {
                $temp[] = array_merge($results, array($key => $value));
            }
        }
        $result = $temp;
    }
    return $result;
}

function get_multipleCombinations($array){
    $count0 = count($array)-1;

    for ($i = 0; $i <= $count0; $i++){
        $result[$i] = get_combinations($array[$i]);
    }
    return($result);

}

function compare_combinations($array){
    $count = count($array)-1;

    for($j = 0; $j <= $count; $j++){
        for($z = 0; $z <= $count; $z++){
            if($j !== $z){
                for($i = 0; $i <= count($array[$j])-1; $i++){
                    if(count($array[$j]) === count($array[$z]) && $array[$j][$i] === $array[$z][$i]){
                        $array[$j][$i] = array("");
                        $array[$z][$i] = array("");
                    }
                }
            }
        }
    }
    return($array);

}

随意批评代码/问题的任何愚蠢部分,我是新手,这将非常有帮助。

感谢您的时间。

1 个答案:

答案 0 :(得分:0)

我想提出的第一个主题是所谓的Big O Notation。我不打算对它进行解释,所以这里有一个链接:What is a plain English explanation of "Big O" notation?

我立刻看到的是所有嵌套的for循环,这严重影响了性能。如果可能的话,建议编写递归函数而不是嵌套的for语句(一般来说循环较少)。

以下是一些可能更好地指导您使用递归而不是嵌套for循环的代码。

function getWordCombos(String $word) {
    $chars = str_split($word);
    return insertHyphens($chars);
}

function insertHyphens(Array $chars, $vals=[], $index=0) {
    //make an untarnished copy of original chars
    $original = $chars;

    for($i=$index; $i<count($original); $i++) {
        $chars = $original;

        //this alters $chars itself, which is why we set $chars = $original above
        array_splice($chars, $i, 1, '_');
        $tempWord = implode('', $chars);

        //setting and checking keys in array faster than in_array
        if (!isset($vals[$tempWord])) {
            $vals[$tempWord]=1;
        }

        //recursive bit
        $vals = insertHyphens($chars, $vals, $index + 1);
    }
    return $vals;
}
$words = "tea tee tail team";

$words = preg_split('/ +/', $words);
$unique = array();
foreach($words as $word) {
    $unique = array_merge($unique, getWordCombos($word));
}

var_dump(implode(' ', array_keys($unique)));

出于性能原因,我最终将该单词的每个组合作为数组键,而不是将其粘贴在数组中what is faster: in_array or isset?

让我感到惊讶的是,发现使用if(!isset($vals[...]))的速度比if(!$vals[...])

两倍的单词数量翻倍所需的时间,2n。增加字符长度也会影响时间量。当我输入一些测试4个char和5个char字时:

  

4个字符12秒,10000次迭代&amp;&amp; 20字

     

10000个迭代的5个字符56秒&amp;&amp; 20字

这增加了超过4.5倍,增加了20个字的字数。当然,这超过10000次迭代,我不确定你要处理多少个单词,或者单词本身的可变长度。

希望这可以帮助你!