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

C++でのパリンドロームパーティショニングIII


小文字と整数kを含む文字列sがあるとします。いくつかのプロパティを維持する必要があります。これらは-

です
  • まず、sの一部の文字(必要な場合)を他の小文字の英字に変更する必要があります。
  • 次に、文字列sをk個の部分文字列に分割して、各部分文字列が回文になるようにします。

文字列を分割するために変更する必要のある最小文字数を見つける必要があります。

したがって、文字列が「ababbc」のようで、k =2の場合、1文字を変更してこれを2つの回文文字列に分割する必要があるため、答えは1になります。したがって、cをbに変更するか、最後から2番目のbをcに変更すると、「bbb」または「cbc」のような1つの回文を取得でき、別の回文は「aba」になります。

これを解決するには、次の手順に従います-

  • サイズが105x105の配列メモを定義します。
  • 関数solve()を定義します。これには、s、idx、k、1つの2D配列> dp、
  • が必要です。
  • idxがsのサイズと同じ場合、-
    • kが0の場合は戻り、それ以外の場合は0を返します
  • memo [idx] [k]が-1に等しくない場合、-
    • return memo [idx] [k]
  • k <=0の場合、-
    • return inf
  • ans:=inf
  • iを初期化する場合:=idx、i
  • ans:=最小のansとdp [idx] [i] +関数solve(s、i + 1、k-1、dp)を呼び出す
  • return memo [idx] [k] =ans
  • メインの方法から、次の手順を実行します
  • n:=sのサイズ
  • メモに-1を入力
  • サイズnxnの2D配列dpを1つ定義します
  • 初期化l:=2の場合、l <=nの場合、更新(lを1増やします)、実行-
    • 初期化i:=0、j:=l --1の場合、j
    • lが2と同じ場合、-
    • dp [i] [j]:=s[i]がs[j]と同じでない場合はtrue
    • それ以外の場合
      • dp [i] [j]:=dp [i + 1] [j --1] + 0(s[i]がs[j]と同じ場合)
  • returnsolve(s、0、k、dp)
  • 理解を深めるために、次の実装を見てみましょう-

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long int lli;
    class Solution {
    public:
       int memo[105][105];
       lli solve(string s, int idx, int k, vector < vector <int> > &dp){
          if(idx == s.size()) {
             return k == 0? 0 : 1000;
          }
          if(memo[idx][k] != -1) return memo[idx][k];
          if(k <= 0)return INT_MAX;
          lli ans = INT_MAX;
          for(int i = idx; i < s.size(); i++){
             ans = min(ans, dp[idx][i] + solve(s, i + 1, k - 1, dp));
          }
          return memo[idx][k] = ans;
       }
       int palindromePartition(string s, int k) {
          int n = s.size();
          memset(memo, -1, sizeof(memo));
          vector < vector <int> > dp(n, vector <int>(n));
          for(int l =2; l <= n; l++){
             for(int i = 0, j = l - 1; j <n; j++, i++){
                if(l==2){
                   dp[i][j] = !(s[i] == s[j]);
                }else{
                   dp[i][j] = dp[i+1][j-1] + !(s[i] == s[j]);
                }
             }
          }
          return solve(s, 0, k, dp);
       }
    };
    main(){
       Solution ob;
       cout << (ob.palindromePartition("ababbc", 2));
    }

    入力

    “ababbc”

    出力

    1

    1. C++での回文分割

      1つの入力文字列があるとします。パーティションのすべてのサブ文字列が回文である場合、その文字列の分割は回文分割です。このセクションでは、指定された文字列をパリンドロームで分割するために必要な最小限のカットを見つける必要があります。したがって、文字列が「ababbbabbababa」のような場合は、回文として分割するための最小カット。ここでは3つのカットが必要です。回文は次のとおりです。ババブ| b |アババ これを解決するには、次の手順に従います- n:=strの長さ それぞれ次数nxnのカット行列とパル行列を定義します for i:=0 to n、do pal [i、i]:=tr

    2. 数値がC++の回文であるかどうかを確認します

      ここでは、番号が回文であるかどうかを確認する方法を説明します。回文数は両方向で同じです。たとえば、番号12321は回文ですが、12345は回文ではありません。 ロジックは非常に単純です。数を逆にする必要があります。逆の数が実際の数と同じである場合、それは回文です。そうでない場合はそうではありません。より良いアイデアを得るためのアルゴリズムを見てみましょう。 アルゴリズム isPalindrome(n)- 入力 −数n 出力 −数値が回文の場合はtrue、それ以外の場合はfalse begin    temp := n    rev :=