一次AC呀,本来想用vector<string>来保存字典,然后暴搜,后来在breeze的提示下想到了用链表数组dict,把字典中的单词按照长度分一下类,然后把长度相同的链在一起,头结点保存在dict[i]中,其中i是单词的长度。虽然最终用了1563MS,但感觉写得还算漂亮,调理比较清晰。
定义了两个结构:
链表:
typedef struct Node
{
string word;
unsigned pos;//记录输入的字典单词在字典中的位置,主要是因为在输出的时候如果有多个候选的单词则要按照候选单词在字典中出现的顺序输出,所以需要保存这个位置
struct Node *next;
}Node;
需要注意的是,结构成员中含有类(string),所以在分配新结点的时候要用new,不能用malloc
用于保存候选单词,及其出现的位置:
typedef struct Result
{
string word;//用于存储可能的单词
unsigned pos;//用于存储这些可能的单词在字典中的位置
}Result;
步骤:
1. 在长度相同的单词链中查找,如果找到完全相同的,则输出,否则如果找到只有一个字母不同的则压入result中;
2. 在长度小1的单词链中查找,找到一个不相等的字符,则比较这个字符之后的串是否相等;
3. 在长度大1的单词链中查找,找到一个不相等的字符,则比较这个字符之后的串是否相等。
输出:
呵呵,没有用排序。。而是先找到result中最小和最大的pos
for(i=min; i<=max; ++i)
{
for(j=0; j<result.size(); ++j)
{
if(result[j].pos == i)
{
cout<<" "<<result[j].word;
break;
}
}
}
貌似效率有点低了,但毕竟result一般不会太大。。。
//Problem: 1035
//Memory: 840K Time: 1563MS
//Language: C++ Result: Accepted
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
#define MAX_WORD_LEN 17
#define MAX_DICT 10000
typedef struct Node
{
string word;
unsigned pos;//记录输入的字典单词在字典中的位置
struct Node *next;
}Node;
typedef struct Result
{
string word;//用于存储可能的单词
unsigned pos;//用于存储这些可能的单词在字典中的位置
}Result;
int main()
{
unsigned i,j,same;
Node *dict[MAX_WORD_LEN];//用一个链表数组来存储词典,把长度相同的单词存在一个链表中
vector<Result> result;//用于存储可能的单词
Result r;
for(i=0; i<MAX_WORD_LEN; ++i)//初始化
{
dict[i] = new Node;//注意struct中有类,分配新节点时要用new
if(dict[i] == NULL)
return -1;
else
{
dict[i]->word = "";
dict[i]->pos = 0;
dict[i]->next = NULL;
}
}
string s;
unsigned pos=0;
Node *node;
Node *p;
cin>>s;
while(s.compare("#"))
{
++pos;
node = new Node;
node->word = s;
node->pos = pos;
node->next = NULL;
p = dict[s.size()];
while(p->next)
{
p = p->next;
}
p->next = node;
cin>>s;
}
cin>>s;
while(s.compare("#"))
{
p = dict[s.size()];
while(p->next)
{
p = p->next;
same = 0;
for(i=0; i<s.size(); ++i)
{
if(s[i]!=(p->word)[i])
{
if(s.compare(i+1,s.size()-(i+1),p->word,i+1,(p->word).size()-(i+1))==0)//找到可以通过替换一个字母得到s的单词
{
r.word = p->word;
r.pos = p->pos;
result.push_back(r);
}
break;
}
else
++same;
}
if(same==s.size())//找到完全相同的单词
{
cout<<s<<" is correct"<<endl;
break;
}
}
if(same!=s.size())//在长度相同的链表中没有找到完全相同的单词,接下来在长度小1和大1的链里面找
{
p = dict[s.size()-1];//在长度小1的链里面找
while(p->next)
{
p = p->next;
//找到第一个不相同的字母的位置,比较s中该位置之后的子串和p->word中该位置开始的子串
//如果这两个子串相同则可以通过删除s中该位置上的字母来得到dict中的单词
for(i=0; i<(p->word).size();++i)
{
if(s[i]!=(p->word)[i])
{
if(s.compare(i+1,s.size()-(i+1),p->word,i,(p->word).size()-i)==0)
{
r.word = p->word;
r.pos = p->pos;
result.push_back(r);
}
break;
}
}
if(i==(p->word).size())//s的前面的s.size()-1个字母都与字典相同,只是多了最后一个字母,可以通过删除该字母达到与字典相同
{
r.word = p->word;
r.pos = p->pos;
result.push_back(r);
}
}
p = dict[s.size()+1];//在长度大1的链里面找
while(p->next)
{
p = p->next;
//找到第一个不相同的字母的位置,比较s中该位置之后的子串和p->word中该位置开始的子串
//如果这两个子串相同则可以通过在s中该位置上添加该字母来得到dict中的单词
for(i=0; i<s.size();++i)
{
if(s[i]!=(p->word)[i])
{
if(s.compare(i,s.size()-i,p->word,i+1,(p->word).size()-(i+1))==0)
{
r.word = p->word;
r.pos = p->pos;
result.push_back(r);
}
break;
}
}
if(i==s.size())//s的前面的s.size()个字母都与字典相同,只是少了最后一个字母,可以通过添加该字母达到与字典相同
{
r.word = p->word;
r.pos = p->pos;
result.push_back(r);
}
}
if(result.size())
{
cout<<s<<":";
unsigned min = MAX_DICT;
unsigned max = 0;
for(i=0; i<result.size(); ++i)
{
if(result[i].pos < min)
min = result[i].pos;
if(result[i].pos > max)
max = result[i].pos;
}
for(i=min; i<=max; ++i)
{
for(j=0; j<result.size(); ++j)
{
if(result[j].pos == i)
{
cout<<" "<<result[j].word;
break;
}
}
}
}
else
cout<<s<<":";
cout<<endl;
}
result.clear();
cin>>s;
}
return 0;
}