<题目链接>

题目大意:

找出能唯一标示一个字符串的最短前缀,如果找不出,就输出该字符串。

解题分析:

Trie树的简单应用,对于每个单词的插入,都在相应字符对应的节点 num 值+1 ,这样在查询的时候,如果遍历到num值为1的节点,就可以确定,该前缀能够唯一确定一个字符串,或者是一直遍历到NULL,这时直接输出它本身即可。

指针式Trie树:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int N =1e3+10;
 7 char word[N][26];
 8 struct Node{
 9     int num;
10     Node *next[26];
11     Node(){
12         num=0;
13         for(int i=0;i<26;i++)
14             next[i]=NULL;
15     }
16 };
17 Node *root;
18 Node *now,*newnode;
19 void Insert(char *str){
20     now=root;
21     for(int i=0;i<strlen(str);i++){
22         int to=str[i]-'a';
23         if(now->next[to]==NULL){   //如果该节点为空
24             newnode=new Node;
25             ++(newnode->num);
26             now->next[to]=newnode;
27             now=now->next[to];
28         }
29         else{
30             now=now->next[to];   
31             ++(now->num);
32         }
33     }
34 }
35 void Search(char *str){
36     char ans[26];
37     now=root;
38     for(int i=0;i<strlen(str);i++){
39         int to=str[i]-'a';
40         now=now->next[to];
41         ans[i]=str[i];    //ans[]记录下前缀字符串
42         ans[i+1]='\0';
43         if(now->num==1){    //如果该节点只有一个对应的公共前缀,那么就是它本身的前缀,所以直接输出该节点的对应前缀即可
44             printf("%s %s\n",str,ans);
45             return;
46         }
47     }
48     printf("%s %s\n",str,str);    
49 }
50 int main(){
51     root=new Node;
52     int cnt=0;
53     while(gets(word[++cnt])){
54         //if(!strlen(word[cnt]))break;
55         Insert(word[cnt]);
56     }
57     for(int i=1;i<=cnt;i++)Search(word[i]);
58     return 0;
59 }

 

数组式Trie树        转载于   >>>

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 char a[10001][31];
 6 int tot,size;
 7 int sz,t[300001][26],s[300001];
 8 void insert(char ch[])
 9 {
10     int k,len=strlen(ch+1),now=0;
11     for(int p=1;p<=len;p++)
12     {
13           k=ch[p]-'a';
14           if(t[now][k]==0)t[now][k]=++sz;
15         now=t[now][k];
16         s[now]++;
17     }
18 }
19 void ask(char ch[])
20 {
21     int now=0,k,len=strlen(ch+1);
22     for(int p=1;p<=len;p++)
23     {
24         if(s[now]==1)break;
25         k=ch[p]-'a';
26         printf("%c",ch[p]);
27         now=t[now][k];
28    }
29 }
30 int main()
31 {
32     while(scanf("%s",a[++tot]+1)!=EOF)insert(a[tot]);
33     for(int i=1;i<=tot;i++)
34     {
35         printf("%s ",a[i]+1);
36         ask(a[i]);
37         printf("\n");
38     }
39     return 0;
40 }

 

 

2018-10-29