Codeforces Round #434 Polycarp's phone book (字典树)

字典树,怎么是字典树呢,把所有的电话都存进去,电话的子串也存进去,每个节点标记上他是第几个数的,有个cnt计数。最后每个数输出最短的那个数。

代码不长很好理解。

#include <bits\stdc++.h>
using namespace std;
#define pb() push_back()
    const int MAX=10;
typedef struct TrieNode                     //Trie结点声明
{
    int cnt,now;                          //now 代表是第几个数字的节点,cnt代表是否是一次
    struct TrieNode *next[MAX];            //儿子分支
}Trie;

void insert1(Trie *root,const char *s,int now1)     //将单词s插入到字典树中
{
    if(root==NULL||*s=='\0')
        return;
    int i;
    Trie *p=root;
    while(*s!='\0')
    {
        if(p->next[*s-'0']==NULL)        //如果不存在,则建立结点
        {
            Trie *temp=(Trie *)malloc(sizeof(Trie));
            for(i=0;i<MAX;i++)
            {
                temp->next[i]=NULL;
            }
            temp->now=now1;
            temp->cnt=1;
            p->next[*s-'0']=temp;
            p=p->next[*s-'0'];
        }
        else
        {
            p=p->next[*s-'0'];
            if(p->now!=now1)
                p->now=now1,p->cnt++;
        }
        s++;
    }
}
string s1[70003];
void sear(Trie *root,string s2)
{
if(root==NULL)return;
for(int i=0;i<MAX;i++)
{
    if(root->next[i]!=NULL)
    {
        char c=(i+'0');
        if(root->next[i]->cnt==1)
        {

            if(s1[root->next[i]->now].length()>s2.length()+1||s1[root->next[i]->now].length()==0)
            {
                s1[root->next[i]->now]=s2;
                s1[root->next[i]->now]+=c;
            }
        }
        sear(root->next[i],s2+c);
    }
}
}
int main(){
  //freopen("test.in","r",stdin);
ios::sync_with_stdio(false);
int n;
cin>>n;

char s[11];
 Trie *root= (Trie *)malloc(sizeof(Trie));
    for(int i=0;i<MAX;i++)
    {
        root->next[i]=NULL;
    }
    root->cnt=0;
    root->now=-1;
for(int i=1;i<=n;i++)
{
    cin>>s;
    for(int j=0;j<9;j++)
    {
        insert1(root,s+j,i);
    }
}
for(int i=1;i<=n;i++)s1[i]="";
sear(root,"");
for(int i=1;i<=n;i++)
    cout<<s1[i]<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值