拼寫檢查-一般解法-程式設計練習題
目錄
問題:1035:拼寫檢查
總時間限制:2000ms 記憶體限制:65536kB
描述
現在有一些英語單詞需要做拼寫檢查,你的工具是一本詞典。需要檢查的單詞,有的是詞典中的單詞,有的與詞典中的單詞相似,你的任務是發現這兩種情況。單詞A與單詞B相似的情況有三種:
1、刪除單詞A的一個字母后得到單詞B;
2、用任意一個字母替換單詞A的一個字母后得到單詞B;
3、在單詞A的任意位置增加一個字母后得到單詞B。
你的任務是發現詞典中與給定單詞相同或相似的單詞。
輸入
第一部分是詞典中的單詞,從第一行開始每行一個單詞,以"#"結束。詞典中的單詞保證不重複,最多有10000個。
第二部分是需要查詢的單詞,每行一個,以"#"結束。最多有50個需要查詢的單詞。
詞典中的單詞和需要查詢的單詞均由小寫字母組成,最多包含15個字元。
輸出
按照輸入的順序,為每個需要檢查的單詞輸出一行。如果需要檢查的單詞出現在詞典中,輸出“?x is correct",?x代表需要檢查的單詞。如果需要檢查的單詞沒有出現在詞典中,則輸出"?x: ?x1 ?x2 ...?xn",其中?x代表需要檢查的單詞,?x1...?xn代表詞典中與需要檢查的單詞相似的單詞,這些單詞中間以空格隔開。如果沒有相似的單詞,輸出"?x:"即可。
樣例輸入
i
is
has
have
be
my
more
contest
me
too
if
award
#
me
aware
m
contest
hav
oo
or
i
fi
mre
#
樣例輸出
me is correct aware: award m: i my me contest is correct hav: has have oo: too or: i is correct fi: i mre: more me
分析:
問題並不難,只要好好分析就可以做出來,不要被描述嚇住。本題只要求有一個字母不同,所以可以分為三種情況:
1、完全相同,最好使用string類,直接使用“==”遍歷字典判斷就可以,
2、長度相等,這種情況直接將不相等的字母替換為相等的字母,然後對比兩個單詞是否相等,如果相等,則代表相似,如果不等,則代表不相似。
3、長度相差1個字母,在短字串與長字串不相等的那個位置,插入多出的那個字元。然後對比兩個單詞是否相等,如果相等,則代表相似,如果不等,則代表不相似。不想等的那個字母位置可能在中間,也可能在末尾,要考慮全。
擴充套件:如果我們想要獲取和字典中單詞有至多2個字母之差的單詞,那麼該如何處理,如果還是分情況討論的話會非常複雜。這就需要使用BK樹來解決,在我們使用字典app時,有沒有發現即使輸錯幾個字母,app依然能給我們推薦想要的單詞,非常智慧。詳見:拼寫檢查程式設計題詳解-BK樹演算法
C++AC程式碼:
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
using namespace std;
bool similar(string lonStr, string shorStr); //判斷單詞相似函式
int main()
{
vector<string> dictionary; //儲存字典單詞
vector<string>::iterator iter; //迭代器
string word; //需要檢查的單詞
string dic;
bool flag = false;
int sub =0;
while(1) //讀入字典單詞
{
cin >> dic;
if(dic == "#")
{
break;
}
dictionary.push_back(dic);
}
while(1) //依次判斷
{
cin >> word;
if(word == "#")
{
break;
}
flag = false;
for(iter = dictionary.begin(); iter != dictionary.end(); iter++) //判斷字典中是否存在該單詞
{
dic = *iter;
if(dic == word)
{
cout << word << " is correct";
flag = true;
}
}
if(!flag) //如果字典中不存在,則查詢是否有相似的單詞
{
cout << word << ":";
for(iter = dictionary.begin(); iter != dictionary.end(); iter++) //遍歷字典,判斷是否相似
{
dic = *iter;
sub = dic.length() - word.length(); //獲取兩個單詞長度之差,如果 <=1,則符合條件,如果>1則不可能匹配成功
if( sub== 0) //兩個單詞長度相同
{
for(int i=0; i< dic.length(); i++)
{
if(dic[i] != word[i])
{
string temp = word; //注意需要新建一箇中間變數temp,不能直接修改單詞word,因為之後還會用到word
temp[i] = dic[i]; //將不相等的單詞替換為相等的單詞,重新比較
if(temp == dic)
{
cout << " "<< dic ;
}
break;
}
}
}else if(abs(sub) == 1) //兩個單詞長度相差1個字母
{
if(dic.length() < word.length())
{
if(similar( word , dic )) //判斷單詞是否相似的函式similar()。
{
cout << " "<< dic;
}
}
else
{
if(similar(dic,word))
{
cout << " "<< dic ;
}
}
}
}
}
cout << endl;
}
return 0;
}
bool similar(string lonStr, string shorStr) //判斷單詞是否相似
{
int lon, shor;
lon = lonStr.length();
shor = shorStr.length();
string temp;
for(int i=0; i<shor; i++)
{
if(lonStr[i] != shorStr[i]) //遍歷每個字母,找到不想等的字母位置
{
temp = shorStr.substr(0,i);
temp = temp + lonStr[i] + shorStr.substr(i,shor-i); //在較短的單詞中插入不想等的字母,然後判斷是否相等。
if(temp == lonStr)
{
return true;
}
}
}
temp = shorStr + lonStr[lon-1]; //以上判斷會漏掉最後一個字母不想等的情況,這裡補上。
if(temp == lonStr)
{
return true;
}
else
{
return false;
}
}
總結:
注意在修改時不能直接修改單詞,應該使用一箇中間變數(替身),因為原單詞我們和字典中其他單詞對比的時候還需要使用。
還有一個就是輸出格式,
cout << " "<< dic ;
空格要在單詞之前。