POJ_1035题解

7 篇文章 0 订阅

传送门:http://poj.org/problem?id=1035

题意:输入很多单词构成一部字典,按#结束字典输入,再输入一些单词,按#结束,查询后来输入的单词是否在字典中存在,若存在则输出  XXXX is correct     若不在字典中存在,则先输出XXXX:,再对该单词进行  删除,替换,插入    操作,判断操作后的单词是否在字典中存在,若存在则输出,若存在多个,则按  这些单词在该字典的输入顺序  输出操作后的单词,若经操作后依然没有该单词,则再输出回车即可。


思路:用Trie树建立字典,对于后来输入的单词在字典中查询,有则输出XXXX is correct,没有则进行   删除,替换,插入  操作,看有无该单词在字典中,有则将该单词放于一数组中,得到所有单词后再排序输出。。


注意:该题有个陷阱     如样例:

be

#

bee

#


若没有进行重判则会输出bee: be be

因此要增加一重判。

 

代码如下:

//Memory:16624KB      Time:204ms
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxnode=150001;

char str[16];

struct node
{
    char str[17];     //17的原因是若该单词的长度是15,加上'\0'就是16,经过插入操作后就会变成17了
    int index;
}ans[19501];            //答案存储的数组
int cnt;

struct Trie              //建立字典树
{
    int ch[maxnode][27];
    int val[maxnode];
    int sz;
    void init(){sz=1;memset(ch,0,sizeof ch);memset(val,0,sizeof val);}
    int idx(char c){return c-'a';}

    void insert(char *s,int v)
    {
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])
                ch[u][c]=sz++;
            u=ch[u][c];
        }
        val[u]=v;                   //val是标记数组,用于标记是否为单词结尾并且是第几个单词,用于后面排序
    }

    int find(char *s)
    {
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])
                return 0;
            u=ch[u][c];
        }
        return val[u];
    }
}t;

void rep(char *s,int len)                  //替换
{
    int x;
    char temp[16];
    for(int i=0;i<len;i++)
    {
        for(char j='a';j<='z';j++)
        {
            strcpy(temp,s);
            temp[i]=j;
            if(x=t.find(temp))
            {
                strcpy(ans[cnt].str,temp);
                ans[cnt++].index=x;
            }
        }
    }
}

void Del(char *s,int len)               //删除
{
    int x;
    char temp[16];
    for(int i=0;i<len;i++)
    {
        for(int j=0;j<i;j++)
            temp[j]=s[j];
        for(int j=i;j<len-1;j++)
            temp[j]=s[j+1];
        temp[len-1]='\0';
        if(x=t.find(temp))
        {
            strcpy(ans[cnt].str,temp);
            ans[cnt++].index=x;
        }
    }
}

void incer(char *s,int len)             //插入
{
    int x;
    char temp[17];                      //插入的temp要为17,理由同上
    for(int i=0;i<=len;i++)
        for(char j='a';j<='z';j++)
        {
            for(int k=0;k<i;k++)
                temp[k]=s[k];
            temp[i]=j;
            for(int k=i;k<len;k++)
                temp[k+1]=s[k];
            temp[len+1]='\0';
            if(x=t.find(temp))
            {
                strcpy(ans[cnt].str,temp);
                ans[cnt++].index=x;
            }
        }
}

bool cmp(node a,node b)
{
    return a.index<b.index;
}

int main()
{
    t.init();
    int len;
    int v=1;
    while(1)                    //字典树的单词插入
    {
        gets(str);
        if(str[0]=='#') break;
        t.insert(str,v);
        v++;
    }
    while(1)                    
    {
        gets(str);
        if(str[0]=='#') break;
        if(t.find(str))
            printf("%s is correct\n",str);
        else
        {
            cnt=0;
            len=strlen(str);
            rep(str,len);               //替换
            Del(str,len);               //删除
            incer(str,len);             //插入
            sort(ans,ans+cnt,cmp);
            printf("%s:",str);
            if(cnt) printf(" %s",ans[0].str);
            for(int i=1;i<cnt;i++)                  //重判
                if(ans[i].index!=ans[i-1].index)        
                    printf(" %s",ans[i].str);
            printf("\n");
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值