Вот измененная версия кода Дмитрий Тарасов (все кредиты ему, пожалуйста), который, кажется, работает правильно.
class Combine {
private static $_result = array();
public static function run($str, $replacements){
self::_run($str, $replacements, 0);
return array_values(array_unique(self::$_result));
}
private static function _run($str, $replacements, $start){
self::$_result[] = $str;
for($i = $start, $l = strlen($str); $i < $l; $i++){
self::_run($str, $replacements, $i+1);
if(isset($replacements[$str[$i]])){
foreach($replacements[$str[$i]] as $key => $val){
$str[$i] = $val;
// call recursion
self::_run($str, $replacements, $i+1);
}
}
}
}
}
print_r( Combine::run($str, $replacements) );
Закрытая функция была введена, чтобы избежать многократного выполнения операций с тяжелыми массивами, в то время как они не используются нигде, кроме корневого вызова.