HDU 1247 Hat’s Words && Trie(字典树)

好久不写字典树,写道水题回忆一下,顺便刷刷题量  O(∩_∩)O哈哈~

题意:给你很多的单词,输出那些可以由其它的两个单词拼接起来的单词。

解法:先把所有单词插入到一个字典树中,然后暴力拆分每个单词,判断两段是不是都是单词,例如:abc  可以拆成 ab c和 a bc 分别判断是不是单词 如果两个都是单词就输出

Trick:题目中要求最后按照字典序输出,但是我没有这样写,直接按照输入顺序输出的,可能是数据太弱了吧。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define pi acos(-1.0)
#define eps 1e-8
using namespace std;
const int maxnode = 500010;
const int char_size = 27;
struct trie
{
    int ch[maxnode][char_size], val[maxnode];
    int sz;
    int idx(char c){return c- 'a';}
    void init(){sz = 1;memset(ch[0],0,sizeof ch[0]);}

    void insert(char* s, int v = 1)
    {
        int u = 0, n = strlen(s);
        for(int i = 0 ; i < n ; ++ i)
        {
            int c = idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof ch[sz]);
                val[sz] = 0;
                ch[u][c] = sz ++;
            }
            u = ch[u][c];
        }
        val[u] = v;
        int a;
        a = 1;
    }

    bool 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 false;
            }
            u = ch[u][c];
        }
        if(val[u]) return true;
        return false;
    }
}tr;

char s[50000][110];

int main()
{
    //freopen("in.txt","r",stdin);
    int n = 0;
    tr.init();
    while(~scanf("%s", s+(n++)))
    {
        int i = n - 1;
        tr.insert(s[i]);
    }
    for(int i = 0 ; i < n ; ++ i)
    {
        for(int j = 1; j < strlen(s[i]) ; ++ j )
        {
            char temp1[100], temp2[100];
            memset(temp1,0,sizeof temp1);
            memset(temp2,0,sizeof temp2);
            strncpy(temp1,s[i],j);
            strncpy(temp2,s[i]+j,strlen(s[i])-j);
            if(tr.find(temp1)&&tr.find(temp2))
            {
                printf("%s\n",s[i]);
                break;
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值