trie 树习题

1.hdu 1305 Immediate Decodability

算法思路:trie树模板,在插入的同时进行统计是否存在,有想法,得动脑子,当脑子空洞的时候,注意要有逻辑判断能力,大胆想,大胆假设

现在假定两个字符串A,B。 A的长度小于B。分两种情况,

当B先输入时(即长的先输入),途经的结点的flag如果为1,即如果有小于B的单词,便为前缀。

当A先输入时(即短的先输入),当建立到A的最后一个字符时, 如果该结点已存在,那么证明,已有一个以该字符为前缀的字符已经输入。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int a[2];int end_;
}trie[2000];
char s[15];
int tot=1;int res=1;
void insert(char s[])
{
    int p=0;int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int t=s[i]-'0';
        if(trie[p].a[t]==0)
            trie[p].a[t]=tot++;
        p=trie[p].a[t];
        if(trie[p].end_==1) res=0;
    }
    trie[p].end_=1;
}
void init(){
    for(int i=0;i<=2000;i++)
    {
        trie[i].a[0]=0,trie[i].a[1]=0,trie[i].end_=0;
    }
    tot=1;res=1;
}
int main()
{
    int num=1;
    while(cin>>s)
    {
        init();insert(s);
        while(cin>>s){
            if(s[0]=='9') break;
            else insert(s);
        }
        if(res==1) printf("Set %d is immediately decodable\n",num);
        else printf("Set %d is not immediately decodable\n",num);
        num++;
    }
    return 0;
}
View Code

2.hdu 1251 统计难题

算法思路:trie树模板,走过一个节点,数量+1;

#include<bits/stdc++.h>
using namespace std;
struct node{
    int a[26],num;
}trie[10000000];
char s[10];int tot=1;
void insert(char s[])
{
    int len=strlen(s);int p=0;
    for(int i=0;i<len;i++)
    {
        int t=s[i]-'a';
        if(trie[p].a[t]==0)
            trie[p].a[t]=tot++;
        p=trie[p].a[t];
        trie[p].num++;
    }
}
int find(char s[])
{
    int p=0;int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int t=s[i]-'a';
        p=trie[p].a[t];
        if(p==0) return 0;
    }
    return trie[p].num;
}
int main()
{
    int tmp=1;
    while(cin.getline(s,20))
    {
        if(strlen(s)==0) {tmp=0;continue;}
        if(tmp==1) insert(s);
        else
        {
            int ans=find(s);
            cout<<ans<<endl;
        }
    }
    return 0;
}
View Code

3.hdu 1671 phone list

算法思路:同1

#include<iostream>
#include<cstdio>
#include<cstring> 
#include<algorithm> 
using namespace std;
const int maxn=1e5+5;
/*struct node{
    int a[10],end;
}trie[maxn];*/
int trie[maxn][10],cmp[maxn];
int res=1,tot=1;char s[20];
void insert(char s[],int k,int n)
{
    int len=strlen(s);int p=0;
    for(int i=0;i<len;i++)
    {
        int t=s[i]-'0';
        if(trie[p][t]==0)
            trie[p][t]=tot++;
        p=trie[p][t];
        if(cmp[p]==1) res=0;
    }
    cmp[p]=1;
    /*if(k==n){
        for(int i=0;i<=9;i++){
            if(trie[p][i]!=0){
                res=0;
                break;
            }
        }
    }*/
    for(int i=0;i<10;i++)
        if(trie[p][i]!=0) res=0;
}
void init()
{
    for(int i=0;i<maxn;i++)
    {
        for(int j=0;j<=9;j++)
        {
            trie[i][j]=0;
        }
        cmp[i]=0;
    }
    tot=1,res=1;
}
int main()
{
    int t;cin>>t;
    while(t--)
    {
        init();
        int n;cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>s;
            if(res)    insert(s,i,n);
            else continue;
        }
        if(res==1) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
} 
View Code

4.hdu 1075  What Are You Talking About

算法思路:火星文替换,trie树模板,增加火星文的空间,如果是结尾时,则将火星文给他,另外这题的gets用法和字符串指针的用法很奇妙

gets会将换行符变为字符串结束符,对字符串的处理能力弱弱弱,另外注意%s时需用getchar吞掉换行符!!

#include<bits/stdc++.h>
using namespace std;
struct node{
    int a[26];char chh[20];int end;
}trie[1000000];int tot=1;
void insert(char *ch1, char *ch2)//ch1 mars,ch2 e  a
{
    int p=0;
    for(int i=0;ch1[i]!='\0';i++)
    {
        int t=ch1[i]-'a';
        if(trie[p].a[t]==0)
            trie[p].a[t]=tot++;
        p=trie[p].a[t];
    }
    trie[p].end=1;strcpy(trie[p].chh,ch2);
}
void query(char *ch1)
{
    int p=0;
    for(int i=0;ch1[i]!='\0';i++)
    {
        int t=ch1[i]-'a';
        p=trie[p].a[t];
        if(p==0)
        {
            printf("%s",ch1);return;
        }
    }
    if(trie[p].end) {
        printf("%s",trie[p].chh);return;
    }
    else {printf("%s",ch1);return;}
}
int main()
{
    char ch1[3010],ch2[3010];
    scanf("%s",&ch1);
    while(~scanf("%s",&ch2))
    {
        if(strcmp(ch2,"END")!=0)
        {
            scanf("%s",&ch1);
            
            insert(ch1,ch2);
        }
        else break;
    }
    scanf("%s",&ch1);//cout<<ch1;
    getchar();
    while(gets(ch1)!=NULL)
    {
        //cout<<ch1;
        if(strcmp(ch1,"END")==0){ break;}
        else
        {
            //cout<<"233";
            int len=strlen(ch1);int tmp=0;char cc;
            ch1[len]='\n';ch1[len+1]='\0';//gets会将换行符变成字符串结束符 
            for(int i=0;i<=len;i++)
            {
                if(!islower(ch1[i]))
                {
                    cc=ch1[i];
                    ch1[i]='\0';//标记为结尾 
                    query(ch1+tmp);
                    tmp=i+1;
                    printf("%c",cc);
                }
            }
        }
    }
    return 0;
}
View Code

5.hdu 3460  Ancient Printer

算法思路:

一开始没有明白题意,看了好久,才明白,原来它是将一个单词打印出来后再在打印机里面删除字母,也就是说,如果单词前缀相同,则只需删除单词不相同的部分,再插入下一个单词不相同的部分。这样的话,可以用字典树,要是单词前缀相同,则在字典树上只有一个结点,那么,要是将最长的那个单词也删除了,则是对字典树上的结点插入一次再删除一次,还要输出n次,也就是2*numnode+n;但是最长的那个单词len不需要删除,则是2*numnode+n-len;
#include<bits/stdc++.h>
using namespace std;
struct node{
    int a[26],end;
}trie[500010];
void init(){
    for(int i=0;i<500010;i++)
    {
        for(int j=0;j<26;j++)
        {
            trie[i].a[j]=0;
        }
        trie[i].end=0;
    }
}
int tot=1;
void insert(char *s)
{
    int p=0;int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int t=s[i]-'a';
        if(trie[p].a[t]==0)
            trie[p].a[t]=tot++;
        p=trie[p].a[t];
    }
    trie[p].end=1;
}
int main()
{
    int n;char s[50];
    while(cin>>n){
        init();tot=1;int maxnum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",&s);
            insert(s);
            int tmp=strlen(s);
            maxnum=max(tmp,maxnum);
        }
        cout<<(tot-1)*2-maxnum+n<<endl; 
    }
    return 0;
}
View Code

6.hdu 2072 单词数

算法思路:其实用字符串处理+trie或者set都可以,重点是字符串的处理。。。。。sscanf,gets的用法,指针不断移动

#include<bits/stdc++.h>
using namespace std;
set<string>aa;//set中第一次加上string 
int main()//语言无非就是字母数字符号了   
{
    while(1)
    {
        char tmp[1000];
        char s[10000];cin.getline(s,10000);//让我复习了getline的用法 
        int nums=strlen(s);
        if(s[0]=='#') break;
        int num=0;
        while(s[num]==' ') num++;//此法可以用来判断非字母的任何作为间隔的东西 
        while(num<nums)//字符串的分割 
        {
            sscanf(s+num,"%s",tmp);
            int len1=strlen(tmp);
            //cout<<len1<<' '<<tmp<<endl;
            aa.insert(tmp);//char到string的自动转换 
            num+=len1;//很不明白题目为什莫要挖这莫多坑 
            num++;//溜了溜了 
            while(s[num]==' ') num++;//消除间隔    ,防止错位 
        }
        cout<<aa.size()<<endl;
        aa.clear();
    }
    return 0;
}
View Code

 

 

转载于:https://www.cnblogs.com/vainglory/p/8505928.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值