<题目链接>
题目大意:
找出能唯一标示一个字符串的最短前缀,如果找不出,就输出该字符串。
解题分析:
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