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

Source

ニコニコミュニティ
問題文

問題概要

文字列 $S$ と $T$ が与えられる.
最初文字列 $S$ が書かれていて,$1$ 回の操作では,$1$ 文字削除する(空いたスペースは詰める),$1$ 文字どこかに挿入する,$1$ 文字書き換える,のどれかを行うことができる.
文字列 $T$ を作るのにかかる最小操作回数を求める問題.

解法

いわゆる編集距離を求める問題.
動的計画法で求めることができる.
$\verb|dp[|i\verb|][|j\verb|]|$ を $S$ の初めの $i$ 文字のみの状態から,$T$ の初めの $j$ 文字のみの状態にするのに必要な最小手数を計算していく.
その際,最後の文字の対応関係を場合分けして漸化式を作る.

C++によるスパゲッティなソースコード

#include<bits/stdc++.h>
using namespace std;

#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)

#define mygc(c) (c)=getchar_unlocked()
#define mypc(c) putchar_unlocked(c)

void reader(int *x){int k,m=0;*x=0;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){*x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||k>'9')break;*x=(*x)*10+k-'0';}if(m)(*x)=-(*x);}
int reader(char c[]){int i,s=0;for(;;){mygc(i);if(i!=' '&&i!='\n'&&i!='\r'&&i!='\t'&&i!=EOF) break;}c[s++]=i;for(;;){mygc(i);if(i==' '||i=='\n'||i=='\r'||i=='\t'||i==EOF) break;c[s++]=i;}c[s]='\0';return s;}
template <class T, class S> void reader(T *x, S *y){reader(x);reader(y);}
void writer(int x, char c){int s=0,m=0;char f[10];if(x<0)m=1,x=-x;while(x)f[s++]=x%10,x/=10;if(!s)f[s++]=0;if(m)mypc('-');while(s--)mypc(f[s]+'0');mypc(c);}
template<class T> void writerLn(T x){writer(x,'\n');}

char memarr[17000000]; void *mem = memarr;
#define MD 1000000007

template<class T> int editDistance(int As, T A[], int Bs, T B[], void *mem){int i,j,k,*d=(int*)mem;rep(i,As+1)d[i*(Bs+1)]=i;rep(i,Bs+1)d[i]=i;REP(i,1,As+1)REP(j,1,Bs+1){k=min(d[i*(Bs+1)+j-1],d[(i-1)*(Bs+1)+j])+1;if(A[i-1]==B[j-1])k= min(k,d[(i-1)*(Bs+1)+(j-1)]);else k=min(k,d[(i-1)*(Bs+1)+(j-1)]+1);d[i*(Bs+1)+j]=k;}return d[As*(Bs+1)+Bs];}

int As, Bs;
char A[1200], B[1200];

int main(){
  int res;

  reader(&As,&Bs);
  reader(A,B);

  res = editDistance(As, A, Bs, B, mem);
  writerLn(res);
  
  return 0;
}

Current time: 2024年04月25日15時02分50秒
Last modified: 2015年06月15日17時35分10秒 (by laycrs)
Tags: Competitive_Programming yukicoder
トップページに戻る

Logged in as: unknown user (not login)

ログイン: