UVA 10391 trie树

8 篇文章 0 订阅
2 篇文章 0 订阅


这个题目就是按照字典序从小到大给你n个字符串 让你找出其中敲好由其他俩个字符串组成的字符串并且输出

这里讲述三种方法 可以自行做出比较

1.暴力  这种方法是最慢的 是第三种方法的时间的10+倍 而且是最麻烦的 需要严谨耳朵逻辑思维和编码能力

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()      //
{
    freopen("in.txt","r",stdin);
    vector<string>vs[26];
    string s;
    while(getline(cin,s))
        if(s.length())vs[s[0]-'a'].push_back(s);
    for(int i=0; i<26; i++)
    {
        if(vs[i].size()>=2)
        {
            for(int j=1; j<vs[i].size(); j++)
            {
                bool judge = true;
                for(int k=0; k<j; k++)
                {
                    if(vs[i][j].find(vs[i][k])==0)//string里面的函数find   查找是不是子串 如果是的话  返回第一个字符的位置  因为这个是前串  所以是0
                    {
                        string t = vs[i][j].substr(vs[i][k].length());//参数可以是一个或者俩个  一个是取子串的位置 一个是长度(如果没有的话就是一直取到末尾)
                        if(!vs[t[0]-'a'].empty())
                        {
                            for(int z=0; z<vs[t[0]-'a'].size(); z++)
                            {
                                if(vs[t[0]-'a'][z]==t)
                                {
                                    if(judge)cout << vs[i][j] << endl;
                                    judge = false;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return 0;
}

2.灵活利用set string  这种方法速度还是可以的 但是也是下面这种方法的3倍左右

#include<iostream>
#include<set>
using namespace std;
int main()
{
    freopen("in.txt","r",stdin);
    set<string> s;
    string tmp;
    while (cin >> tmp)       s.insert(tmp);
    set<string>::iterator it = s.begin();
    for (it; it != s.end(); it++)
    {
        tmp = *it;
        for (int i = 1; i < tmp.length(); i++)
        {
            if (s.find(tmp.substr(0, i)) != s.end() && s.find(tmp.substr(i, tmp.length() - i)) != s.end())
            {
                cout << tmp << endl;
                break;
            }
        }
    }
    return 0;
}


3.trie 树的结果 也就是利用单词的前缀进行匹配 这种方法是最快的

#include <cstdio>
#include <cstring>

const int sonnum = 26;
char word[120005][30];
struct trie
{
    bool term;
    struct trie *son[sonnum];
};

trie* create_trie()
{
    trie *temp = new trie;
    temp -> term = false;
    for(int i = 0;i <sonnum;i++)
    {
        temp -> son[i] =NULL;
    }

    return temp;
}

void insert_word(trie *pnt,char s[],int len)
{
    trie *temp = pnt;
    for(int i = 0;i <len;i++)
    {
        if(temp -> son[s[i] - 'a'] == NULL)
            temp -> son[s[i] - 'a'] = create_trie();
        temp = temp -> son[s[i] - 'a'];
    }
    temp -> term = true;
}

bool find(trie *pnt ,char s[],int len)
{
    trie *temp = pnt;
    for(int i = 0;i <len ;i ++)
    {
        if(temp -> son[s[i] - 'a'] == NULL)
            return false;
        temp = temp -> son[s[i] - 'a'];
    }

    if(temp -> term)
    return true;
    return false;
}

int main()
{
    int n = 0;
    trie *t = create_trie();
    while(scanf("%s",word[n]) == 1)
    {
        insert_word(t,word[n],strlen(word[n]));
        n++;
    }

    for(int i = 0;i < n;i ++)
    {
        char s1[30],s2[30];
        int len = strlen(word[i]);
        for(int j = 1;j < len ;j ++)
        {
            int k;
            for(k = 0;k < j;k++)
            {
                s1[k] = word[i][k];
            }
            s1[k] = '\0';

            for(k = j;k < len;k ++)
            {
                s2[k-j] = word[i][k];
            }
            s2[k-j] = '\0';
            if(find(t,s1,strlen(s1))&&find(t,s2,strlen(s2)))
            {
                printf("%s\n",word[i]);
                break;
            }
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值