开始入手字典树了,第一个题其实就是一波三折啊!这个题目一开始在我看了白书上的基本代码之后写的然后就一直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;
}