1043 {
1044 std::vector<std::vector<double> > costs(
1045 left.size() + 1, std::vector<double>(right.size() + 1));
1046 std::vector<std::vector<EditType> > best_move(
1047 left.size() + 1, std::vector<EditType>(right.size() + 1));
1048
1049
1050 for (size_t l_i = 0; l_i < costs.size(); ++l_i) {
1051 costs[l_i][0] = static_cast<double>(l_i);
1053 }
1054
1055 for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) {
1056 costs[0][r_i] = static_cast<double>(r_i);
1057 best_move[0][r_i] = kAdd;
1058 }
1059
1060 for (size_t l_i = 0; l_i < left.size(); ++l_i) {
1061 for (size_t r_i = 0; r_i < right.size(); ++r_i) {
1062 if (left[l_i] == right[r_i]) {
1063
1064 costs[l_i + 1][r_i + 1] = costs[l_i][r_i];
1065 best_move[l_i + 1][r_i + 1] = kMatch;
1066 continue;
1067 }
1068
1069 const double add = costs[l_i + 1][r_i];
1070 const double remove = costs[l_i][r_i + 1];
1071 const double replace = costs[l_i][r_i];
1072 if (
add < remove &&
add < replace) {
1073 costs[l_i + 1][r_i + 1] =
add + 1;
1074 best_move[l_i + 1][r_i + 1] = kAdd;
1075 }
else if (remove <
add && remove < replace) {
1076 costs[l_i + 1][r_i + 1] =
remove + 1;
1077 best_move[l_i + 1][r_i + 1] =
kRemove;
1078 } else {
1079
1080
1081 costs[l_i + 1][r_i + 1] = replace + 1.00001;
1082 best_move[l_i + 1][r_i + 1] =
kReplace;
1083 }
1084 }
1085 }
1086
1087
1088 std::vector<EditType> best_path;
1089 for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) {
1090 EditType move = best_move[l_i][r_i];
1091 best_path.push_back(move);
1092 l_i -= move !=
kAdd;
1094 }
1095 std::reverse(best_path.begin(), best_path.end());
1096 return best_path;
1097}
bool remove(const path &p)