C++
 Computer >> コンピューター >  >> プログラミング >> C++

文字列Sを部分列として含む回文文字列を求めるC++プログラム

長さnの文字列Sが与えられたとします。このとき、Tが回文であり、かつSがTの部分列(サブシーケンス)となるような文字列Tを見つける必要があります。

例えば、入力が S = "ab" の場合、出力は "abba" となります(他にも "aabaa" など、複数の正解が存在します)。

解法のアプローチ

この問題は、非常にシンプルな発想で解くことができます。以下の手順に従います。

  1. 結果の文字列resをSで初期化します。
  2. 文字列Sを反転します。
  3. resに反転したSを連結します。
  4. resを返します。

つまり、元の文字列とその逆順の文字列を連結するだけで、必ず回文となる文字列を作ることができます。中央を境に左右が対称になるため、結果は常に回文の条件を満たします。また、元の文字列Sが前半にそのまま含まれているため、Sは結果の部分列にもなっています。

実装例

以下のC++コードで実装を確認してみましょう。

#include <bits/stdc++.h>
using namespace std;
string solve(string S){
    string res = S;
    reverse(S.begin(), S.end());
    res += S;
    return res;
}
int main(){
    string S = "ab";
    cout << solve(S) << endl;
}

入力

ab

出力

abba

計算量について

このアルゴリズムの時間計算量はO(n)です。文字列の反転と連結はいずれも線形時間で実行できるため、非常に効率的です。空間計算量も結果の文字列を格納するためにO(n)必要となります。シンプルながら、あらゆる入力文字列に対して確実に回文を生成できる優れたアプローチです。

  1. C++で、ある文字列の部分列のうち別の文字列の部分文字列となる最長のものの長さを求める

    問題の概要2つの文字列XとYが与えられたとき、Xの部分列のうち、Yの部分文字列(連続する一部分)として現れるものの中で最も長いものの長さを求めます。例えば、X = ABCD、Y = BACDBDCD の場合、出力は 3 になります。これは「ACD」がXの部分列であり、同時にYの部分文字列でもある最長の文字列だからです。動的計画法によるアプローチこの問題は動的計画法(DP)を使うことで効率的に解けます。Xの長さをn、Yの長さをmとすると、(m+1)×(n+1) のサイズのDPテーブルを作成します。DP[i][j] は「X[0…j] の部分列のうち、Y[0…i] の部分文字列となっているものの最大

  2. 【C++】復号化した文字列からk番目の文字を取得する方法

    問題の概要エンコードされた文字列を考えてみましょう。この形式では、部分文字列の繰り返しが「部分文字列 + 繰り返し回数」で表現されます。たとえば、ab2cd2 という文字列は ababcdcd を意味します。ここで k = 4 が与えられた場合、復号化後の文字列の4番目の文字、つまり b を返すことになります。解法のアプローチこの問題は、以下の手順で解くことができます。まず空の復号化用文字列を用意します。元の文字列を先頭から読み込み、英小文字が続く限り部分文字列として抽出します。続いて数字が続く限り読み取り、繰り返し回数として記録します(複数桁の数値にも対応)。抽出した部分文字列を、記録した回