開始入手字典樹了,第一個題其實就是一波三折啊!這個題目一開始在我看了白書上的基本代碼之後寫的然後就一直wa了,感覺自己寫的是對的啊,但是一直找不出毛病,稍後在最後面貼上代碼,希望有人看出來能給予指正,不甚感激。
這個題目的話作爲第一個題來說讓我學會了兩種寫法,一種是靜態的寫法,另外一種是動態的寫法,靜態的寫法感覺更加好寫一些,只需要在開點內存的時候把內存開的大一些即可了,然後動態的寫法就是每次到新的點需要重新開點,然後就是可能需要使用到free來把內存給消掉。
解題的思路是一樣的,都是考慮在每一個結點出放一個指標count,在建立該字典樹的時候每次的字母讀到這個字母的時候都要進行一次++做累加,然後比如banana和bee,那麼b就累加了兩次,而b之後的anana和ee都只有一次。那麼查詢的時候當讀到對面的字母時返回這個count值就可以了。
靜態寫法:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxnode=400000;
const int nsize=26;
char a[15];
struct Trie
{
int ch[maxnode][nsize];
int val[maxnode];
int sz;
void myTrie() {sz=1; memset(ch[0],0,sizeof(ch[0])); }
int idx(char c) { return c-'a'; }
void insert(char *s)
{
int u=0,n=strlen(s);
for(int i=0;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
val[u]++;
}
}
int search(char *s)
{
int n=strlen(s),u=0,ss=0;
for(int i=0;i<n;i++)
{
int id=idx(s[i]);
if(ch[u][id]==0)
return 0;
u=ch[u][id];
if(i==n-1)
ss=val[u];
}
return ss;
}
}one;
int main()
{
one.myTrie();
while(gets(a))
{
if(a[0]=='\0')
break;
one.insert(a);
}
while(gets(a))
{
if(a[0]=='\0')
break;
int ans=0;
ans=one.search(a);
printf("%d\n",ans);
}
return 0;
}
動態寫法:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
struct node
{
int count;
node *child[26];
node()
{
count=0;
int i;
for(i=0;i<26;i++)
{
child[i]=NULL;
}
}
};
node *root=new node;
node *current,*newnode;
void insert(char *s)
{
int i,m;
current=root;
for(i=0;i<strlen(s);i++)
{
m=s[i]-'a';
if(current->child[m]!=NULL)
{
current=current->child[m];
++(current->count);
}
else
{
newnode=new node;
++(newnode->count);
current->child[m]=newnode;
current=newnode;
}
}
}
int search(char *s)
{
int i,m;
current=root;
for(i=0;i<strlen(s);i++)
{
m=s[i]-'a';
if(current->child[m]==NULL)
{
return 0;
}
current=current->child[m];
}
return current->count;
}
int dealTrie(node* T)
{
//動態字典樹,有時會超內存,這是就要記得釋放空間了
if(T==NULL)
return 0;
for(int i = 0; i <26; i++)
{
if(T->child[i]!=NULL)
dealTrie(T->child[i]);
}
free(T);
return 0;
}
int main()
{
char a[20];
while(gets(a))
{
if(a[0]=='\0')
break;
insert(a);
}
while(gets(a)!=NULL)
{
printf("%d\n",search(a));
}
dealTrie(root);
return 0;
}
野路子 寫法:
#include <cstdio>
#include <iostream>
#include <map>
#include <cstring>
#include <string>
using namespace std;
int main()
{
char str[17];
map<string, int> m;
while(gets(str))
{
int len = strlen(str);
if (!len)
{
break;
}
for(int i = len; i > 0; i--)
{
str[i] = '\0';
m[str]++;
}
}
while(gets(str))
{
cout<<m[str]<<endl;
}
return 0;
}
自己的第一次的wa了的寫法(懇請大神看看,我的思路也不是count的思路而是搜素的思路0.0)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxnode=1000000;
const int nsize=26;
char a[15];
struct Trie
{
int ch[maxnode][nsize];
int val[maxnode];
int sz;
void myTrie() {sz=1; memset(ch[0],0,sizeof(ch[0]));}
int idx(char c) { return c-'a'; }
void insert(char *s,int v)
{
int u=0,n=strlen(s);
for(int i=0;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
}
int counts(int u)
{
int ans=0;
for(int i=0;i<26;i++)
{
if(val[u])
{
ans++;
return ans;
}
if(ch[u][i]!=0)
{
ans+=counts(ch[u][i]);
}
}
return ans;
}
int search(char *s)
{
int n=strlen(s),u=0;
for(int i=0;i<n;i++)
{
int id=idx(s[i]);
if(ch[u][id]==0)
return false;
u=ch[u][id];
}
int ss=counts(u);
return ss;
}
}one;
int main()
{
one.myTrie();
while(gets(a))
{
if(a[0]=='\0')
break;
one.insert(a,1);
}
while(gets(a))
{
if(a[0]=='\0')
break;
int ans=0;
ans=one.search(a);
printf("%d\n",ans);
}
return 0;
}