问题分析
输入:名字的数字标识
输出:通讯录中所有和该标识匹配的记录
约束:错误匹配的概率不能太高
解答思路
1. 给通讯录中的记录附加上标识字段( 数字 )
2. 将通讯录中的记录按照标识字段进行排序
3. 用户输入要查找的人的名字的标识字段( 这里的标识字段类型要经过整理才能转换为 1 中的标识字段类型 详见下面代码的相关部分注释 )
4. 顺序输出所有和 3 中标识字段匹配的记录
代码实现
1 #include <iostream> 2 #include <fstream> 3 #include <string> 4 #include <map> 5 6 using namespace std; 7 8 // 初始化通讯录函数 9 // --- 为每个记录附加一个标识符字段 10 void init( multimap<string, string> &m, fstream &io ); 11 12 // 标识符获取函数 13 // --- 将名字字符串转化为对应的标识符 14 string getST( const string & name ); 15 16 // 查询记录函数 17 // --- 根据用户给定的标识符,检索通讯录并输出结果。 18 void search( multimap<string, string> &m, string &st ); 19 20 int main(void) 21 { 22 // 打开通讯录 23 string filename; 24 cout << "输入要创建的数据文件名: " << endl; 25 cin >> filename; 26 27 fstream io; 28 io.open(filename.c_str()); 29 if (!io) { 30 cout << "打开文件失败!" << endl; 31 return 1; 32 } 33 34 // 初始化通讯录 35 multimap<string, string> m; 36 init(m, io); 37 38 // 获取用户输入标识符 39 string st; 40 cout << "请输入要查找人名的数字标识符: "; 41 cin >> st; 42 43 // 检索通讯录并输出结果 44 search(m, st); 45 46 // 关闭文件流 47 io.close(); 48 49 return 0; 50 } 51 52 void init(multimap<string, string> &m, fstream &io) { 53 string name; 54 string st; 55 56 // 遍历通讯录,并将各组信息及对应标识符存入 multimap 表中。 57 while (io >> name) { 58 st = getST(name); 59 m.insert(make_pair(st, name)); 60 } 61 62 return; 63 } 64 65 string getST(const string & name) { 66 string st = "000000000"; 67 68 for (int i=0; i<name.length(); i++) { 69 if (name[i] == ‘a‘ || name[i] == ‘b‘ || name[i] == ‘c‘) 70 st[0]++; 71 if (name[i] == ‘d‘ || name[i] == ‘e‘ || name[i] == ‘f‘) 72 st[1]++; 73 if (name[i] == ‘g‘ || name[i] == ‘h‘ || name[i] == ‘i‘) 74 st[2]++; 75 if (name[i] == ‘j‘ || name[i] == ‘k‘ || name[i] == ‘l‘) 76 st[3]++; 77 if (name[i] == ‘m‘ || name[i] == ‘n‘ || name[i] == ‘o‘) 78 st[4]++; 79 if (name[i] == ‘p‘ || name[i] == ‘q‘ || name[i] == ‘r‘) 80 st[5]++; 81 if (name[i] == ‘s‘ || name[i] == ‘t‘ || name[i] == ‘u‘) 82 st[6]++; 83 if (name[i] == ‘v‘ || name[i] == ‘w‘ || name[i] == ‘x‘) 84 st[7]++; 85 if (name[i] == ‘y‘ || name[i] == ‘z‘) 86 st[8]++; 87 } 88 89 return st; 90 } 91 92 void search( multimap<string, string> &m, string &st ) 93 { 94 // 将用户输入的标识符格式转换成内存中存放的标识符格式 95 string st1 = "000000000"; 96 for (int i=0; i<st.length(); i++) { 97 int t = (int)st[i] - (int)‘0‘; 98 st1[t]++; 99 } 100 101 // 检索通讯录,并获取结果范围。 102 multimap<string, string> :: iterator up, low; 103 low = m.lower_bound(st1); 104 up = m.upper_bound(st1); 105 106 // 切记要加入以下程序段,否则可能会因为无法读取下面的 low->first 而发生错误。 107 if (low == up && low == m.end()) { 108 cout << "无任何匹配记录" << endl; 109 return; 110 } 111 112 // 打印检索到的记录 113 cout << endl << "找到如下人名: " << endl; 114 while (low->first != up->first) { 115 cout << low->second << endl; 116 low++; 117 } 118 119 cout << endl << endl; 120 121 return; 122 }
运行测试
1. 建立带有如下记录的通讯录( 普通文本格式 )
2. 按照以下规则:
abc 0 def 1 ghi 2 jkl 3 mno 4
pqr 5 stu 6 vwx 7 yz 8
建立并输入要查询的人名的标识符,如要查 fangmeng ,则可输入 10424142 并获取查询结果:
小结
1. 通过修改标识符的生成格式及比对规则,可以形成不同的模糊匹配规则。使用何种模糊匹配规则应结合具体情况决定。
2. 标识法的灵活性体现在可以根据不同的需要建立不同意义的标识。
第 2 章 第 6 题 通讯录模糊检索问题 标识法实现,布布扣,bubuko.com
原文:http://www.cnblogs.com/scut-fm/p/3639499.html