POJ 1035 Spell checker

trie树做的,看discuss说,暴力貌似可以。

主要trick就是匹配到的字符串可能重复,要注意去重

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;
#define MAX 300000
struct node
{
    int flag;
    int tag;
    int next[26];
    int init()
    {
        memset(next,-1,sizeof(next));
        flag=0;
        tag=0;
        return 0;
    }
}trie[MAX];
struct asdf
{
    char s[20];
};

int size;
const int root=0;
int val(char a)
{
    return a-'a';
}
map<string,int> mp;
int lm,ls;
struct textmem
{
    char s[20];
};
textmem lstr[10000];

int insert(char *s)
{
    int i,p=root;
    for (i=0; s[i]; i++)
    {
        int v=val(s[i]);
        if (trie[p].next[v] == -1)
        {
            trie[p].next[v]=size;
            trie[size].init();
            size++;
        }
        p=trie[p].next[v];
    }
    trie[p].tag=1;
    return 0;
}
int match(char *s)
{
    int p=root,i;
    for (i=0; s[i]; i++)
    {
        int v=val(s[i]);
        p=trie[p].next[v];
        if (p == -1)
            break;
        if (trie[p].tag && s[i+1] == '\0')
            return 1;
    }
    return 0;
}

void deleteLetter(char *str)
{
    char t[20];
    int i,j,k;
    for (i=0; str[i]; i++)
    {
        for (j=0,k=0; str[k]; j++,k++)
        {
            if (k == i)
            {
                j--;
                continue;
            }
            t[j]=str[k];
        }
        t[j]='\0';
        if (match(t))
        {
            strcpy(lstr[ls].s,t);
            ls++;
        }
    }
}
void replaceLetter(char *str)
{
    int i,j,k;
    char t[20];
    for (i=0; str[i]; i++)
    {
        for (j=0; j<26; j++)
        {
            for (k=0; str[k]; k++)
            {
                if (k == i)
                    t[k]='a'+j;
                else
                    t[k]=str[k];
            }
            t[k]='\0';
            if (match(t))
            {
                strcpy(lstr[ls].s,t);
                ls++;
            }
        }
    }
}
void insertLetter(char *str)
{
    int i,j,k,s,lt;
    char t[20];
    s=strlen(str);
    for (i=0; i<=s; i++)
    {
        for (j=0; j<26; j++)
        {
            lt=0;
            for (k=0; str[k]; k++)
            {
                if (k == i)
                {
                    t[lt]=j+'a';
                    lt++;
                    t[lt]=str[k];
                    lt++;
                }
                else
                {
                    t[lt]=str[k];
                    lt++;
                }
            }
            if (i == s)
            {
                t[lt]=j+'a';
                lt++;
            }
            t[lt]='\0';
            if (match(t))
            {
                strcpy(lstr[ls].s,t);
                ls++;

            }
        }
    }
}
bool cmp(textmem a,textmem b)
{
    return mp[a.s] < mp[b.s];
}
int main()
{
    int i,n,j;
    char str[20];
    lm=0;
    mp.clear();
    for (i=0; i<MAX; i++)
    {
        trie[i].init();
    }
    size=1;
    while (1)
    {
        scanf("%s",str);
        if (str[0] == '#')
            break;
        insert(str);
        mp[str]=lm;
        lm++;
    }
    while (1)
    {
        scanf("%s",str);
        if (str[0] == '#')
            break;
        if (match(str))
        {
            printf("%s is correct\n",str);
            continue;
        }
        ls=0;

        deleteLetter(str);
        replaceLetter(str);
        insertLetter(str);

        sort(lstr,lstr+ls,cmp);
        printf("%s:",str);
        for (i=0; i<ls; i++)
        {
            if (i == 0 || strcmp(lstr[i-1].s,lstr[i].s) != 0)
            printf(" %s",lstr[i].s);
        }
        printf("\n");
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值