1228 {
1229 std::vector<std::vector<double> > costs(
1230 left.size() + 1, std::vector<double>(right.size() + 1));
1231 std::vector<std::vector<EditType> > best_move(
1232 left.size() + 1, std::vector<EditType>(right.size() + 1));
1233
1234
1235 for (size_t l_i = 0; l_i < costs.size(); ++l_i) {
1236 costs[l_i][0] = static_cast<double>(l_i);
1238 }
1239
1240 for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) {
1241 costs[0][r_i] = static_cast<double>(r_i);
1242 best_move[0][r_i] =
kAdd;
1243 }
1244
1245 for (size_t l_i = 0; l_i < left.size(); ++l_i) {
1246 for (size_t r_i = 0; r_i < right.size(); ++r_i) {
1247 if (left[l_i] == right[r_i]) {
1248
1249 costs[l_i + 1][r_i + 1] = costs[l_i][r_i];
1250 best_move[l_i + 1][r_i + 1] =
kMatch;
1251 continue;
1252 }
1253
1254 const double add = costs[l_i + 1][r_i];
1255 const double remove = costs[l_i][r_i + 1];
1256 const double replace = costs[l_i][r_i];
1257 if (add < remove && add < replace) {
1258 costs[l_i + 1][r_i + 1] = add + 1;
1259 best_move[l_i + 1][r_i + 1] =
kAdd;
1260 } else if (remove < add && remove < replace) {
1261 costs[l_i + 1][r_i + 1] = remove + 1;
1262 best_move[l_i + 1][r_i + 1] =
kRemove;
1263 } else {
1264
1265
1266 costs[l_i + 1][r_i + 1] = replace + 1.00001;
1267 best_move[l_i + 1][r_i + 1] =
kReplace;
1268 }
1269 }
1270 }
1271
1272
1273 std::vector<EditType> best_path;
1274 for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) {
1275 EditType move = best_move[l_i][r_i];
1276 best_path.push_back(move);
1277 l_i -= move !=
kAdd;
1279 }
1280 std::reverse(best_path.begin(), best_path.end());
1281 return best_path;
1282}