読者です 読者をやめる 読者になる 読者になる

へなちょここーだー

プログラミング初心者がtopcoderなどの競技プログラミングに挑戦。勉強したアルゴリズムなどを書いていきます。現在topcoder緑でcodeforces青。どちらもDiv1昇格を目指しています。

yukicoder No.225 文字列変更(medium)

yukicoderに参戦。No.225は解けなかったけれど、自分にとって良いレベルの問題だったためメモ。
コンテスト中に書いたコードは以下の通り。

#include <iostream>
#include <algorithm>
using namespace std;

int solve(string s, string t, int n, int m, int itr = 0){
  if(itr == m)
    return 0;
  if(itr == n)
    return m - n;
  if(s[itr] == t[itr])
    return solve(s, t, n, m, itr + 1);

  int mincost;
  mincost = solve(s, t, n, m, itr + 1) + 1;
  mincost = min(mincost, solve(s.substr(1, n - 1), t, n - 1, m, itr) + 1);
  mincost = min(mincost, solve("a" + s, t, n + 1, m, itr + 1) + 1);
  return mincost;
}

int main(){
  int n, m;
  cin >> n >> m;
  string s, t;
  cin >> s >> t;
  cout << solve(s, t, n, m) << endl;
}

基本的に考え方はこれで良かったはず。TLEになってしまいましたが、自分の中ではここまでコードを書けるようになってすこし満足。でも、上を見ましょう。後はこれをDynamic Programmingで効率的に解きましょう。

#include <iostream>
#include <algorithm>
using namespace std;

#define MAX 1100
#define INF 1<<29

void chmin(int& a, int b){
  if(a > b)
    a = b;
}

int n, m;
string S, T;
int dp[MAX][MAX];

int main(){
  cin >> n >> m;
  cin >> S >> T;
  S += "-"; T += "-";
  for(int i = 0; i < MAX; i++)
    for(int j = 0; j < MAX; j++)
      dp[i][j] = INF;
  dp[0][0] = 0;
  for(int i = 0; i <= n; ++i){
    for(int j = 0; j <= m; ++j){
      if(S[i] == T[j])
        chmin(dp[i+1][j+1], dp[i][j]);
      else
        chmin(dp[i+1][j+1], dp[i][j] + 1);
      chmin(dp[i+1][j], dp[i][j] + 1);
      chmin(dp[i][j+1], dp[i][j] + 1);
    }
  }
  cout << dp[n][m] << endl;
}

模範解答をほぼ丸パクリですね...でも良い勉強になりました。
全探索が出来るようになってきたのでDPを極めるぞ!!!