poj 1035 Spell Checker

/*
    poj 1035 Spell Checker

    题目大意:
        给定一堆字符串作为字典,判断单词是否在字典中,或则可以由字典中的哪些单词演化得到?
        演化规则:单词b可以通过单词a添加、删除或者替换一个字母得到。

    解题思路:
        因为题目要求需要按照字典中单词的顺序输出所有相似的单词(可演化得到目的单词的),因此
        没法使用Trie或者hash之类的快速查找结构 -- 因为不是单纯查找是否存在!

        采用最直接的方法,顺序遍历字典,判断每个单词是否与目的单词相似或者相同。
        如果相同,停止遍历,输出结果。
        如果相似,记录单词下标,直到字典遍历完毕,输出所有相似单词。
*/

#include <iostream>
#include <cstdio>
#include <cstring>

namespace {
    using namespace std;

    const int STR_LEN_MAX = 15;
    const int DIC_SIZE_MAX = 10000;

    char DIC[DIC_SIZE_MAX][STR_LEN_MAX+1]; // 单词表
    unsigned char L[DIC_SIZE_MAX];   // 单词长度记录表

    unsigned short CL[DIC_SIZE_MAX]; // 近似链,记录相近单词所在字典的下标

    // 计算两单词不同的字符个数
    int diff(const char *pWord1, int l1, const char *pWord2, int l2)
    {
        int i=0, j=0;
        
        int count = 0;
        for (i=0, j=0; i<l1&&j<l2;)
        {
            if (pWord1[i]!=pWord2[j])
            {
                if (l1<l2)      // 增加一个字符的情况
                    ++j;

                if (l1 == l2 )  // 替换的情况,同时++
                {
                    ++i; ++j; 
                }

                if (l1 > l2 )   // 删除一个字符的情况
                    ++i;
                
                ++count;
            }
            else
            {
                ++i; ++j;
            }
        }

        count += ((l2-j)+(l1-i)); // 要把没比完的字符个数加上
        
        return count;
    }
}

int main()
{
    int dicSize = 0;
    while (EOF!=scanf("%s", DIC[dicSize]) && DIC[dicSize][0]!='#')
    {
        L[dicSize] = strlen(DIC[dicSize]);
        
        ++dicSize;
    }

    int l, num;
    char word[STR_LEN_MAX+1];
    while (EOF!=scanf("%s", word) && word[0]!='#')
    {
        l = strlen(word);
        
        num = 0;
        int i;
        for (i=0; i<dicSize; i++)
        {
            // 这3种情况之外,不处理
            if (l!=L[i] && l!=L[i]-1 && l!=L[i]+1) 
                continue;

            int dn = diff(DIC[i], L[i], word, l);
            if (dn == 0)
            {
                num = 0; // DIC[i]与单词word完全相同,停止迭代
                break;
            }
            else if (dn == 1)
            {
                CL[num++] = i; // DIC[i]与单词word相似,记录下标
            }
            else
            {
                // do nothing
            }
        }

        if (num==0 && i!=dicSize)
        {
            printf("%s is correct\n", word);
        }
        else
        {
            printf("%s:", word);
            for (int i=0; i<num; i++)
            {
                printf(" %s", DIC[CL[i]]);
            }
            printf("\n");
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值