您的位置:首页 > 其它

字典树模板

2016-05-16 19:22 399 查看

字典树

字典树
模板
1 模板一

2 模板二

题目链接I

题目链接II

题目链接III

竞赛时应该采用数组形式来写,易查错


详细讲解

1.模板

1.1 模板一

struct Node
{
int v;
Node *next[M];
}*root;

void Creat(char *s) //分配内存最好使用calloc 因为会进行初始化 而malloc不初始化 都是随机的数据垃圾
{
int len = strlen(s);
Node *p = root, *q;

for(int i=0; i<len; i++)
{
int id = s[i] - 'a';
if(p->next[id] == NULL)
{
q = (Node *)calloc(1, sizeof(Node));
q->v = 1;
p->next[id] = q;
p = q;
}
else
{
p = p->next[id];
p->v++;
}
}
p->v = -1; //标志最后一个为-1
}

int Find(char *s) //查找函数可更具需要修改
{
int len  = strlen(s);
Node *p = root;
for(int i=0; i<len; i++)
{
int id = s[i] - 'a';
p = p->next[id];
if(p == NULL)
return 0; //不存在
if(p->v == -1)
return -1;//已有串是此串前缀
}
return 1;// 此串是某已有串的前缀
}


1.2 模板二

tree[i][j]表示节点i的那个编号为j的子节点


int top;// top 表示节点个数
int tree[M][27]; // 字典树
int val[M]; //可赋予意义 例如为字符串的权值 当val[i] 大于0时i是单词节点
//或者记录某个节点出现的次数
void init()
{
top=1;
memset(tree[0],0,sizeof tree[0]);
}

void insert(char *s, int v)//v 表示该单词权值信息
{
int Len=strlen(s);
int u=0;
for(int i=0;i<Len;i++)
{
int c=s[i] - 'a';
if(!tree[u][c])
{
memset(tree[top], 0, sizeof tree[top])
val[top]=0;
tree[u][c]=top++;
}
u=tree[u][c];
}
val[u]=v;//这里表示该值为单词节点
}


2.题目链接I

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
using namespace std;
char s[1005][21];

struct node
{
int cnt;
node *next[27];
}*root;

void maketree(char *str)
{
int ans,len;
node *p,*q;//设置两个临时指针
p=root;
len=strlen(str);
for(int i=0;i<len;i++)
{
ans=str[i]-'a';//用来记录不同字符
if(p->next[ans]!=NULL)
{
p=p->next[ans];//表示不同节点的值
p->cnt++;
}
else
{
q=(node *)calloc(1,sizeof(node));//申请新的节点
p->next[ans]=q;
p=q;
p->cnt=1;
}
}
}

void findtree(char *str)
{
int ans,len;
node *p;
p=root;
len=strlen(str);
for(int i=0;i<len;i++)
{
ans=str[i]-'a';
p=p->next[ans];
printf("%c",str[i]);
if(p->cnt==1)
break;
}
cout<<endl;
}
int main()
{
int n=0;
root=(struct node *)calloc(1,sizeof(node));//为将要建立的链表申请一个新节点
while(~scanf("%s",s
))
{
maketree(s[n++]);
if(n==12)
break;
}
for(int i=0;i<n;i++)
{
printf("%s ",s[i]);
findtree(s[i]);
}
}


3.题目链接II

I.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MOD 998244353
#define M 2000010
using namespace std;

int top;// top 表示节点个数
int tree[M][4]; // 字典树
int val[M]; //字符串的权值 当val[i] 大于0时i是单词节点

void init()
{
top=1;
memset(tree, 0, sizeof tree);
memset(val, 0, sizeof val);
}

void insert(int v)
{
int u = 0;//根节点
for(int i = 0; i < 30 ; i++)
{
int t = v & ( 1<< i );
if(t) t = 1;
if(!tree[u][t])
{
val[top] = 1;
tree[u][t] = top++;
}
else
{
val[tree[u][t]]++;
}
u = tree[u][t];
}
}

int ans;
void find(int v)
{
int u = 0;
for(int i = 0; i < 30; i++)
{
int t = v & (1 << i);
if(t) t = 1;
if(tree[u][t ^ 1])
ans = ( ans + (val[tree[u][t ^ 1]]) * (1 << i)) % MOD;
u = tree[u][t] ;
}
}

int a[M];

int main()
{
int T, n;
scanf("%d", &T);
int kase = 0;
while(T--)
{
init();
ans = 0;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%d", &a[i]);
insert(a[i]);
}
for(int i=0; i<n; i++)
find(a[i]);
printf("Case #%d: %d\n", ++kase, ans);
}
return 0;
}


II.

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;
#define maxn 50005
const int M = 2;
const int MOD = 998244353;
int a[maxn];

struct Node
{
int cnt;
Node *next[M];
}*root;

void insert(int v)
{
Node *p = root, *q;
for(int i=0; i<30; i++)
{
int  t = v&(1<<i);
if(t) t = 1;
if(p->next[t] == NULL)
{
q = (Node*)calloc(1, sizeof(Node));
q->cnt = 1;
p->next[t] = q;
p = q;
}
else
{
p = p->next[t];
p->cnt++;
}
}
}

int ans;

void find(int v)
{
Node *p = root;
for(int i=0; i<30; i++)
{
int t = v&(1<<i);
if(t) t = 1;
if(p->next[t^1])
{
ans = (ans + (p->next[t^1]->cnt) * (1<<i)) % MOD;
}
p = p->next[t];
}
}

int kase = 0;

int main()
{
int T, n;
scanf("%d", &T);
while(T--)
{
ans = 0;
root = (Node*)calloc(1, sizeof(Node));
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%d", &a[i]);
insert(a[i]);
}
for(int i=0; i<n; i++)
find(a[i]);
printf("Case #%d: %d\n", ++kase, ans);
}
return 0;
}


4.题目链接III

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
#define maxn 400000 + 10
#define M 300000 + 10
#define mod 20071027

int tree[maxn][27], val[maxn], top;
int d[maxn];
char s[M], tmp[105];

void init()
{
top = 1;
memset(tree[0], 0, sizeof tree[0]);
memset(d, 0, sizeof d);
}

void insert(char *s, int v)
{
int len = strlen(s), u = 0;
for(int i = 0; i < len; i++)
{
int c = s[i] - 'a' ;
if(!tree[u][c])
{
memset(tree[top], 0, sizeof tree[top]);
val[top] = 0;
tree[u][c] = top++;
}
u = tree[u][c];
}
val[u] = v;
}

int len ;

int query(char *s, int pos)
{
int u = 0;
int res = 0;
for(int i = pos; i < len; i++)
{
int c = s[i] - 'a' ;
u = tree[u][c];
if(!u) return res;
if(val[u])
{
res = (res + d[i + 1] ) % mod ;
}
}
return res;
}

int main()
{
int kase = 0;
while(~scanf("%s", s))
{
init();
len = strlen(s);
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%s", tmp);
insert(tmp, 1);
}
d[len] = 1;
for(int i = len - 1; i >= 0; i--)
{
d[i] = query(s, i);
}
printf("Case %d: %d\n", ++kase, d[0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: