// Score function int calculate_score( const ID& a, const ID& b ) { int len_a = a.size(); int len_b = b.size(); int s = 0; int L = (len_a < len_b) ? len_a:len_b; int dL = abs(len_a - len_b); s = dL * (dL + 1) / 2; for (int i = L-1; i >= 0; --i) { s += ((a[i] == b[i]) ? 0:(L-i)); } return s; }
void AccountMap::Existing( const ID& id ) { vector<ID*> list_id(10); vector<int> list_score(10); int target_score = 1; int num_compare = id.size() - 1; int score_temp; int size = 0; SkipListNode* front; SkipListNode* back; // Set the iteratro go to front and back Find(id, front); back = Next(front); // Stop when get enough data, or two iterator are at the end while ((front->data_id.front() != '!' || back->data_id.front() != '{') && \ (size != 10 || list_score[10] > target_score) ) { // First move front iteratro while (front->data_id.front() != '!' && \ (num_compare == 0 || id.compare(0, num_compare, front->data_id, 0, num_compare) == 0) ) { score_temp = calculate_score(id, front->data_id); if (size < 10 || score_temp <= list_score.back()) { insert_id_to_vector(list_id, list_score, 0, front->data_id, score_temp, size); } front = Previous(front); } // If get enough data, stop if (size == 10 && list_score[10] <= target_score) break; // If data is not enough, move back iterator while (back->data_id.front() != '{' && \ (num_compare == 0 || id.compare(0, num_compare, back->data_id, 0, num_compare) == 0) ) { score_temp = calculate_score(id, back->data_id); if (size < 10 || score_temp < list_score.back()) { insert_id_to_vector(list_id, list_score, 1, back->data_id, score_temp, size); } back = Next(back); } // Add the tolerent to score, adjust the number of string to compare target_score += 1; if (num_compare > 0) num_compare -= 1; } // Print the result bool comma = false; for (int i = 0; i < (int)list_score.size(); ++i) { if (comma) { cout << ','; } cout << *(list_id[i]); comma = true; } }
// Return whether two char* is matching, a may have wildcard bool match_recursion( const ID& a, const ID& b, int pa, int pb ) { if (pa == (int)a.size() && pb == (int)b.size()) { return true; } if (a[pa] == '?' || a[pa] == b[pb]) { return match_recursion(a, b, pa+1, pb+1); } if (a[pa] == '*' && pa+1 != (int)a.size() && pb == (int)b.size()) { return false; } if (a[pa] == '*') { return match_recursion(a, b, pa+1, pb) || match_recursion(a, b, pa, pb+1); } return false; }
// Change text to the next one accrording to dictionary order // The part that can be changed is between string[min_len] and string[max_len-1] // Retrun true if succeed, false if the next one doesn't exist bool next_string( ID& text, int min_len, int max_len ) { if ((int)text.size() < max_len) { text.append("0"); return true; } while (text.back() == 'z') { text.pop_back(); if ((int)text.size() == min_len) { return false; } } char c = text.back(); if (c == '9') { text.back() = 'A'; } else if (c == 'Z') { text.back() = 'a'; } else { text.back() += 1; } return true; }
void AccountMap::Unused( const ID& id ) { int target_score = 1; int len = id.size(); int min_len = len - 1; int max_len = (len+1 < 100) ? (len+1):100; int output = 0; bool comma = false; SkipListNode* temp; string test; if (min_len == 0) { test = "0"; } else { test = id.substr(0, min_len); } while (output < 10) { if (calculate_score(test, id) == target_score && !Find(test, temp)) { if (comma) { cout << ','; } cout << test; comma = true; output += 1; } if (!next_string(test, min_len, max_len)) { target_score += 1; min_len = (min_len == 0) ? 0:(min_len-1); if (max_len != 100 && (max_len+1-len+1)*(max_len+1-len)/2 <= target_score) { max_len += 1; } if (min_len == 0) { test = "0"; } else { test = id.substr(0, min_len); } } } }