拼写检查-一般解法-编程练习题

目录

问题:1035:拼写检查

分析:

C++AC代码:

总结:


问题: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 ;

空格要在单词之前。

posted @ 2018-11-10 23:42  CatOnRoad  阅读(529)  评论(0编辑  收藏  举报