HDU 1247 Hat’s Words(trie树+STL)

Hat’s Words

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10889    Accepted Submission(s): 3903


Problem Description
A hat’s word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary.
You are to find all the hat’s words in a dictionary.
 

Input
Standard input consists of a number of lowercase words, one per line, in alphabetical order. There will be no more than 50,000 words.
Only one case.
 

Output
Your output should contain all the hat’s words, one per line, in alphabetical order.
 

Sample Input
  
  
a ahat hat hatword hziee word
 

Sample Output
  
  
ahat hatword
 


题目大意:

给出一些字符串,输出其中的部分字符串,这些字符串可以拆分成其他字符串。


解题思路:
首先用map标记字符串是否出现过,然后按照长度从小到大排序。然后我们就可以从小到大将字符串加入到trie树中,当遇到节点不存在的情况,就把从这一位开始的字符串取出,判断这些字符串是否存在。
举个栗子:a,hat,ahat这3个字符串,首先将a和hat放入trie树中。然后将ahat放入trie树中,当要放入h时,我们发现ah这个前缀不存在,所以我们要把h作为一个字符串存起来,之后每放入一个字符,我们就更新所有的字符串,最终形成了hat这个字符串,经过预处理map["hat"]已经等于1,即已经存在了,那么我们就可以输出ahat。
注意:这种方法有一个缺陷,就是处理aa,aaaa时会输出aaaa,所以我们要特判这种情况,当map["aa"]大于等于2时才能输出aaaa。


参考代码:

#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps=1e-10;
const int INF=0x3f3f3f3f;
const int MAXN=50000+50;
typedef long long LL;
struct node
{
    LL v;
    node* next[26];
    node()
    {
        v=0;
        memset(next,NULL,sizeof(next));
    }
}*root;

string word[MAXN];
map<string,int>m;

bool trie_insert(node* start,string word)
{
    int len=word.size();
    node* now=start;
    vector<string>v;
    v.clear();
    for(int i=0; i<len; i++)
    {
        int id=word[i]-'a';
        if(now->next[id]==NULL)
            now->next[id]=new node();
        now=now->next[id];
        for(int j=0; j<v.size(); j++)
                v[j]+=word[i];
        if(now->v)
            v.push_back("");
    }
    now->v++;
    for(int i=0; i<v.size(); i++)
    {
        if(m[v[i]]&&v[i]!=word)
        {
            bool ok=true;
            int l=v[i].size();
            for(int j=1;j<l;j++)
            {
                if(v[i][j]!=v[i][j-1])
                {
                    ok=false;
                    break;
                }
            }
            if(ok&&len==l*2&&m[v[i]]>=2)//特判aa,aaaa
                return true;
            if(!ok||len!=l*2)
                return true;
        }
    }
    return false;
}

LL trie_query(node* start,char* word)
{
    int len=strlen(word);
    node* now=start;
    for(int i=0; i<len; i++)
    {
        int id=word[i]-'a';
        if(now->next[id]==NULL)
            return 0;
        now=now->next[id];
    }
    return now->v;
}

void trie_del(node *now)
{
    for(int i=0; i<26; i++)
        if(now->next[i]!=NULL)
            trie_del(now->next[i]);
    delete now;
}


int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
    int cnt=0;
    root=new node();
    while(cin>>word[++cnt])
    {
        if(m[word[cnt]]==0)
            m[word[cnt]]=1;
        else
            m[word[cnt]]++;
    }
    cnt--;
    sort(word+1,word+1+cnt);
    for(int i=1; i<=cnt; i++)
        if(trie_insert(root,word[i]))
            cout<<word[i]<<endl;
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值