【trie树 / STL】——hdu1247——trie叫做字典树,map又何尝不是一种字典?

                                        Hat’s Words

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


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
 
题意:在字典中寻找一个单词,如果这个词可以有字典中的其他两个词合并而成,则这个词叫做hat’s word,输出所有的hat’s word
 
思路一:
          map+vector逆向思维,降低复杂度。
           即:看一个单词是否可以划分为两个字典中已经存在的单词。
代码如下:
#include<map>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
int main()
{
    vector<string> v;
    map<string, int> m;

    string str, s1, s2;

    while(cin>> str)
    {
        v.push_back(str);
        m[str]++;
    }

    for(int i = 0; i < v.size(); i++ )
    {
        str = v[i];
        s1 = "";
    //看字符串str能否分为字典里存在的两个字符串
        for(int j = 0; j + 1 < str.size(); j++ )
        {
            s1 += str[j];
            s2 = str.substr(j + 1);
            if(m[s1] && m[s2])
            {
                cout<< str<< endl;
                break;
            }
        }
    }
    return 0;
}

 

思路二:

          trie树,和法一思路一致

代码如下:

(代码长,不过时间短)

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

char ch[50050][100];

struct node{
    struct node*next[26];//记录子节点内容
    bool vis;//该结点是否存在一个单词

    node()//构造函数初始化一个结点
    {
        for(int i=0;i<26;i++)
            next[i]=NULL;
        vis=false;
    }
}*root;

//插入函数
void inset(char s[])
{
    int k=0;
    node *p=root;

    //从一个子树枝走到底,如果走不通了,就造新节点往下走
    while(s[k]!='\0')
    {
        if(!p->next[s[k]-'a'])
        {
            p->next[s[k]-'a']=new node();
        }

        p=p->next[s[k]-'a'];
        k++;
    }

    p->vis=true;//最后一个节点标记为真,表示存在到此位置的一个单词
}

bool fid(char s[])
{
    int k=0;
    node *p=root;//从根向下遍历

    //一直按照线索找下去
    while(s[k]!='\0'&&p->next[s[k]-'a'])
    {
        p=p->next[s[k]-'a'];
        k++;
    }

    //字符串找完且该点为真
    if(s[k]=='\0'&&p->vis)
    {
        return p->vis;
    }

    //该路径小于字符串长度
    return false;
}

int main()
{
    int i=0;
    int k;
    root=new node();

    while(scanf("%s",ch[i])!=EOF)
    {
        inset(ch[i]);
        i++;
    }

    for(int k=0;k<i;k++)
    {
        for(int j=1;j<strlen(ch[k])-1;j++)
        {
            char s1[105];
            char s2[105];

            for(int jj=0;jj<j;jj++)
            {
                s1[jj]=ch[k][jj];
            }

            s1[j]='\0';
            strcpy(s2,ch[k]+j);

            if(fid(s1)&&fid(s2))
            {
                cout<<ch[k]<<endl;
                break;
            }
        }
    }
    return 0;
}

 

posted @ 2016-06-14 15:16  琥珀川||雨露晨曦  阅读(184)  评论(0)    收藏  举报