紫书刷题进行中,题解系列点这里
习题3-11 UVA1588 Kickdown(44行AC代码)
思路分析
给定两个数字串,仅由1、2组成,当相应位置不同时为2时,说明两个位置匹配,这题本质就是找最长匹配长度max,两个数字串长度总和-max即为结果。
假设数字串a,b,且a长度小于b,且固定b,向右移动a,考虑三种位置情况:
- a在b左侧
- a在b内部
- a在b右侧
简单遍历,每次取最小即可
注意点
-
a在b的左侧容易遗忘
-
题目明确要求无需考虑反转,若反转,有些结果会变小,比如
12,12
会变成2,正确应是3 -
可通过增加线段起点,统一3中情况,优化代码,参考博文
AC代码(C++11,双串匹配)
#include<bits/stdc++.h>
using namespace std;
string a, b;
int getMin(string a, string b) { // 获取a和b最小的组合长度
if (a.size() > b.size()) swap(a,b); // a为短者
int MIN = a.size() + b.size();
for (int i = a.size(); i > 0; i --) { // a的长度;a在b左侧
int j;
for (j = 0; j < i; j ++) {
if (a[a.size()-i+j] == '2' && b[j] == '2') break;
}
if (j == i) { // 找到第一个符合
MIN -= i;
break;
}
}
for (int i = 0; i <= b.size()-a.size(); i ++) { // b的起始位置;a包含于b
int j;
for (j = 0; j < a.size(); j ++) {
if (a[j] == '2' && b[i+j] == '2') break;
}
if (j == a.size()) {
MIN = b.size();
break;
}
}
for (int i = a.size()-1; i > 0; i --) { // a的长度;a在b右侧
int j;
for (j = 0; j < i; j ++) {
if (a[j] == '2' && b[b.size()-i+j] == '2') break;
}
if (j == i) {
MIN = min(MIN, (int)(a.size()+b.size()-i));
break;
}
}
return MIN;
}
int main() {
while(cin >>a >>b) {
printf("%d\n", getMin(a,b));
}
return 0;
}