因为第一次接触字典树,所以参考了别人的代码,在这里要感谢http://hi.baidu.com/sulipol/blog/item/741f7c11c8bcfa0c203f2e4f.html该blog的博主,发表这么一篇通俗易懂的代码,让我明白字典树是怎么一回事!
这题是给出n个单词,有m个询问,注意,这些询问可以是单词的子序列,所以建树的时候要去重,具体怎样去重呢?就是先把第一个单词的各个子序列建立一棵字典树,建树的时候要标记当前的id,就是第几个单词,相同的跳过,例如有单词abab,其中ab,ab是它的子序列,建树的时候就注意跳过处理!建树同时也要记录到达次数,也就是组成当前单词的有几个。轮到第二个单词也一样。
询问的时候就一个个字母遍历就好,当遇到字母的id为0时就输出0。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <deque>
#include <stack>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <limits.h>
#include <time.h>
#include <string.h>
using namespace std;
int lowbit(int t){return t&(-t);}
int countbit(int t){return (t==0)?0:(1+countbit(t&(t-1)));}
int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);}
#define LL long long
#define PI acos(-1.0)
#define N 500000
#define Max INT_MAX
#define Min INT_MIN
#define eps 1e-8
#define FRE freopen("a.txt","r",stdin)
struct node{
int inid; //inid是当前子序列属于第几个单词,方便去重
int pass; //记录组成当前的单词有几个
int next[26];
}p[N];
int num;
void add(char *str,int beg,int si){
int pos=0;
int i,j;
for(i=beg;str[i];i++){
int id=str[i]-'a';
if(p[pos].next[id]==0) //开始没判断,导致多出很多相同节点>_<
p[pos].next[id]= ++num; //记录此结点的id
pos=p[pos].next[id];
if(p[pos].inid==si) continue; //去重处理
p[pos].inid=si;
p[pos].pass++;
}
}
void substr(char *str,int si){
int i;
for(i=0 ; str[i] ; i++){
add(str,i,si);
}
}
void find(char *str){
int i,j;
int pos=0;
for(i=0;str[i];i++){
int id=str[i]-'a';
pos=p[pos].next[id];
if( pos==0 ){
printf("0\n");
return ;
}
}
printf("%d\n",p[pos].pass);
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
int i,j;
num=0;
memset(p,0,sizeof(p));
char str[22];
for(i=1;i<=n;i++){
scanf("%s",str);
substr(str,i);
}
int m;
scanf("%d",&m);
while(m-- && scanf("%s",str)){
find(str);
}
}
return 0;
}
贴一个MLE的,真郁闷!数组开到50w不会MLE,用链表竟然MLE!原因已查明,next指针开大了一点点
![抓狂](http://static.blog.csdn.net/xheditor/xheditor_emot/default/crazy.gif)
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <deque>
#include <stack>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <limits.h>
#include <time.h>
#include <string.h>
using namespace std;
#define LL long long
#define PI acos(-1.0)
#define Max INT_MAX
#define Min INT_MIN
#define eps 1e-8
#define FRE freopen("a.txt","r",stdin)
struct Node{
Node *next[26];
int inid;
int pass;
Node(){
pass=0;
inid=0;
for(int i=0;i<26;i++)
next[i]=NULL;
}
};
void add(char *str,int beg,int si,Node *root){
int i,j;
Node *pos=root;
for(i=beg;str[i];i++){
int id=str[i]-'a';
if(pos->next[id]==NULL)
pos->next[id]=new Node();
pos=pos->next[id];
if(pos->inid==si)continue;
pos->inid=si;
pos->pass++;
}
}
void substr(char *str,int si,Node *&root){
int i,j;
if(root==NULL)root=new Node();
for(i=0;str[i];i++){
add(str,i,si,root);
}
}
void find(Node *root,char *str){
int i,j;
Node *pos=root;
for(i=0;str[i];i++){
int id=str[i]-'a';
if(pos->next[id]==NULL){
printf("0\n");
return ;
}
pos=pos->next[id];
}
printf("%d\n",pos->pass);
}/*
void release(Node *root)
{
int i;
Node *cur = NULL;
cur = root;
for (i = 0; i < 26; ++i){
if (cur->next[i] != NULL){
release(cur->next[i]);
}
}
delete(root);
root = NULL;
}*/
int main(){ //FRE;
int n;
char str[22];
Node *root;
while(scanf("%d",&n)!=EOF){
int i,j;
root=NULL;
for(i=1;i<=n;i++){
scanf("%s",str);
substr(str,i,root);
}
int m;
scanf("%d",&m);
while(m-- && scanf("%s",str)){
find(root,str);
}
}
return 0;
}