Как я могу решить «проблему декодирования строки» с помощью манипуляций со строками?

#php #arrays #string #algorithm #stack

Вопрос:

Я наткнулся Decode string problem на то, что дается закодированная строка s, расшифруйте ее с помощью правила:
N[encoded] => encoded*N .

Примеры:

 $input = "4[abc]";
// output: abcabcabcabc

$input = "ac3[ab]d";
// output: acabababd

$input = "a2[b3[cd]]";
// output: abcdcdcdbcdcdcd
 

Я попытался решить эту проблему, используя манипуляцию строками с условиями if, она работает только для двух входов, однако в конце концов она завершается неудачей, когда данный вход содержит несколько закодированных строк.

 $output = '';
$arr = str_split($input);
for ($i=0; $i < count($arr); $i  ) { 
    $char = $arr[$i];//current character
    if($char == '['){
        $closed = strpos($input, ']');
        $len = $closed - ($i 1);
        $output .= str_repeat(substr($input, $i 1, $len), $prev);
        $i = strpos($input, ']');
    }elseif(ctype_digit($char)){
        $prev = $char;
    }else{
        $output .= $char;
    }
}
echo $output;
 

Есть ли какие-либо способы ее решения с использованием того или иного подхода. Или это можно решить только с помощью стека?
Спасибо за любую идею, которая может помочь решить эту проблему!

Комментарии:

1. Просто любопытно — что не так с подходом к стеку? Это кажется более интуитивным и естественным в данном случае.

Ответ №1:

Чтобы решить вложенный [], вы должны расшифровать его изнутри. Решение использует preg_replace_callback до тех пор, пока не останется ничего, что можно было бы заменить.

 function fkdecode($str){
  while(true){
  $newStr = preg_replace_callback('~(d )[([^[]] )]~',
    function($m){
      return str_repeat($m[2],(int)$m[1]);
    },
    $str);
   if($newStr == $str) break;
   $str = $newStr;
  }
  return $str;
}

//test
$inputs = ["4[abc]", // output: abcabcabcabc
 "ac3[ab]d", // output: acabababd
 "a2[b3[cd]]", // output: abcdcdcdbcdcdcd
];

foreach($inputs as $input){
  echo $input.' := '. fkdecode($input)."<br>n";
}
 

Выход:

 4[abc] := abcabcabcabc
ac3[ab]d := acabababd
a2[b3[cd]] := abcdcdcdbcdcdcd
 

Ответ №2:

Используйте strpos() со смещением ( $i в вашем случае), указанным для декодирования нескольких закодированных строк.

Вы могли бы использовать strlen вместо count. Это делается для того, чтобы избежать ошибки преобразования массива в строку. Кроме того, вы должны принять во внимание случай, когда N > 9.

 $output = '';

for ($i = 0; $i < strlen($input); $i  ) { 
    $char = $input[$i];//current character
    if($char == '['){
        $closed = strpos($input, ']', $i);
        $len = $closed - ($i 1);
        $output .= str_repeat(substr($input, $i 1, $len), $prev);
        $i = strpos($input, ']', $i);
    }elseif(ctype_digit($char)){
        $end = strpos($input, '[', $i);
        $len = $end - $i;
        $prev = substr($input, $i, $len);
        $i = strpos($input, '[', $i) - 1;
    }else{
        $output .= $char;
    }
}

echo $output;
?>
 

Кстати, это не решает проблему вложенности [] . Вы могли бы использовать стек, чтобы решить эту проблему. Подсказка: Проверьте, есть ли [ «до $closed «. Или используйте этот подход, не связанный с O(n).