ACM/ICPC 2011 Asia Regional - Daejeon
Problem C - Color Length
問題概要
N台の車の列とM台の車の列が与えられます。
これらの車は、'A'〜'Z'の色のどれかで塗られています。
N台の車の列とM台の車の列を順番を変えずに、マージした列Sを作ります。
文字列Sにおいて、以下の方法によって求めたコストの最小値を求めてください。
<コストの計算法>
- 文字列Sにおいて、「文字Cが存在する末尾index - 文字Cが存在する先頭index」を求める
- これを全ての文字の種類について求め、それらを合計した値がコスト
プログラム
int n, m; string a, b; int dp[5002][5002]; int alpha[128]; int aCnt[5002][128], bCnt[5002][128]; //文字列sの各アルファベットの数の累積和を求める //t[i][j] = sのi文字目までで、jの文字がいくつあったか //alpha[i] = iの文字が、2つの文字列を合わせていくつあったか void countAlpha(const string &s, int t[5002][128]){ int len = s.length(); for(int i = 0; i < len; i++){ alpha[s[i]]++; for(int j = 'A'; j <= 'Z'; j++){ if(s[i] == j){ t[i + 1][j]++; } t[i + 1][j] += t[i][j]; } } } int getCost(int i, int j, char ch){ int res = 0; //chが先頭文字列であるとき if(aCnt[i][ch] + bCnt[j][ch] == 1){ res -= i + j; } //chが末尾文字列であるとき if(aCnt[i][ch] + bCnt[j][ch] == alpha[ch]){ res += i + j; } return res; } void solve(){ for(int i = 0; i <= n; i++){ for(int j = 0; j <= m; j++){ dp[i][j] = INT_MAX; } } dp[0][0] = 0; for(int i = 0; i <= n; i++){ for(int j = 0; j <= m; j++){ if(dp[i][j] == INT_MAX) continue; //1つ目の文字列を1文字進められる if(i + 1 <= n){ dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + getCost(i + 1, j, a[i])); } //2つ目の文字列を1文字進められる if(j + 1 <= m){ dp[i][j + 1] = min(dp[i][j + 1], dp[i][j] + getCost(i, j + 1, b[j])); } } } cout << dp[n][m] << endl; } int main(){ int T; cin >> T; while(T--){ cin >> a >> b; n = a.length(); m = b.length(); memset(alpha, 0, sizeof(alpha)); memset(aCnt, 0, sizeof(aCnt)); memset(bCnt, 0, sizeof(bCnt)); countAlpha(a, aCnt); countAlpha(b, bCnt); solve(); } }