我已经组装了这个小算法,能够创建所有可能的字母和下划线的列表(茶 - > 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);
}
随意批评代码/问题的任何愚蠢部分,我是新手,这将非常有帮助。
感谢您的时间。
答案 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次迭代,我不确定你要处理多少个单词,或者单词本身的可变长度。
希望这可以帮助你!