题目大意:
题目出自:http://poj.org/problem?id=1035
你是一个新开发的“魔法检验系统”程序的程序员。现在系统中的一个模块由你开发。首先,数据中给了你一本字典,以“#”结束,单词数不超过10000个,单词的长度不超过15个字符,且均由小写字母组成。之后给了你一些待检验的单词,你需要按照以下规则检查单词:
(1)如果单词在字典中出现过,输出“xxx is correct”以空格分隔。
(2)如果不然,先输出“xxx:”,然后输出可能的正确单词以回车结束。(如果没有可能的正确单词,你必须在冒号后面直接输出回车。)
(3)“可能的正确单词”必须满足:修改原单词增加一个字母可以变成这个单词或者删除待检验的单词以“#”结束。
解法:
这道题开始想法:输入一个单词,去字典里面“暴力”搜索,即去求该单词与字典里每一个单词的编辑距离。当距离等于0时,表示该单词是正确的,停止搜索输出“xxx is correct”;当没有编辑距离等于的0单词时,即记录下所有编辑距离单词为1的单词;如果没有编辑距离为1的单词,则输出“单词:”。按照这个想法,后来提交上去,超时了(即时间复杂度太高)。
后来也是看了讨论里面的帖子,发现可以这样解:
(1)将单词按照单词的长度hash,同时要存储每个字典单词的位置,因为输出结果要求按字典里面的单词顺序输出。
(2)当输入单词的长度为len的时候,这是需要检查hash[len-1]、 hash[len] 、hash[len+1]三个表就行了,这当然期间有可能len=1,此时就只有搜索len=1和len=2的单词(因为没有长度为0的单词),还有可能len=15,只需检查len=14和len=15(按照题目要求,单词最长为15)。
(3)将得到的结果按照字典的输入顺序排序输出。
代码:
#include <iostream> #include <string> #include <vector> #include <utility> #include <algorithm> using namespace std; class spellChecker{ public: void solution() { vector<pair<string,int> >dic[15]; vector<string>dic1; string str; int rank = 0; while(cin>>str&&str!="#"){ dic[str.size()-1].push_back(make_pair(str,rank++)); dic1.push_back(str); } string word; while(cin>>word&&word!="#"){ vector<int>result; vector<pair<string,int> >::iterator iter; bool res = false; int len = word.size()-1; int start = len<=0?0:len-1; int end = len>=14?14:len+1; for(int index = start;index<=end;index++){ for(iter=dic[index].begin();iter!=dic[index].end();++iter){ pair<string,int> w = *iter; string str1 = w.first; int dis = checkString(word,str1); if(dis==0){ res = true; goto R; } if(dis==1)result.push_back(w.second); } } R:if(res)cout<<word<<" is correct"<<endl; else{ cout<<word<<": "; sort(result.begin(),result.end()); for(int i=0;i!=result.size();i++) cout<<dic1[result[i]]<<" "; cout<<endl; } } } private: // int min(int a,int b,int c) // { // int t = a<b?a:b; // return t<c?t:c; // } // int Distance(string strA,int pAbegin,int pAend,string strB,int pBbegin,int pBend)//用这种递归方法,也会超时 // { // if(pAbegin>pAend){ // if(pBbegin>pBend)return 0; // else return pBend-pBbegin+1; // } // if(pBbegin>pBend){ // if(pAbegin>pAend)return 0; // else return pAend-pAbegin+1; // } // if(strA[pAbegin]==strB[pBbegin]) // return Distance(strA,pAbegin+1,pAend,strB,pBbegin+1,pBend); // else{ // int a = Distance(strA,pAbegin+1,pAend,strB,pBbegin,pBend); // int b = Distance(strA,pAbegin+1,pAend,strB,pBbegin+1,pBend); // int c = Distance(strA,pAbegin,pAend,strB,pBbegin+1,pBend); // return min(a,b,c)+1; // } // } int checkString(const string& str1, const string& str2) { int cnt = 0; if (str1.size() < str2.size()) { int i = 0, j = 0; while(i < str1.size() && j < str2.size()) { if (str1[i] != str2[j])++cnt,++j; else ++i,++j; } cnt += str1.size() - i + str2.size() - j; } else if (str1.size() == str2.size()) { for (int i = 0; i < str1.size(); ++i) if (str1[i] != str2[i])++cnt; } else cnt = checkString(str2, str1); return cnt; }; }; int main() { spellChecker poj1035; poj1035.solution(); system("pause"); return 0; }