一次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;
}