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


    目录

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

    空格要在单词之前。

  • 相关阅读:
    VS项目如何运用svn的忽略列表
    Hyper-V如何应用新的网卡
    android:Layout_weight的深刻理解
    使用WebView出现web page not available
    如何在android模拟器中导入搜狗输入法?
    ASP.Net生成静态HTML页
    微软URLRewriter.dll的url重写的简单使用(实现伪静态)
    servlet中获得tomcat项目根目录的绝对路径
    Log4j使用指南
    处理URL传递中文乱码问题
  • 原文地址:https://www.cnblogs.com/www-helloworld-com/p/10202950.html
Copyright © 2020-2023  润新知