字典树

1.动态分配空间
const int N = 27;
struct trie{
trie *Next[N];
int flag;
trie(){
flag=1;
memset(Next,NULL,sizeof(Next));
}
}*root;
void insert(string s){
int len=s.length();
trie *p=root,*q;
for(int i=0;i<len;i++){
int id=s[i]-'a';
if(p->Next[id]==NULL){
q=new trie();
p->Next[id]=q;
p=p->Next[id];
}else{
p=p->Next[id];
(p->flag)++;
}
}
}
int query(string s){
int len=s.length();
trie *p=root;
for(int i=0;i<len;i++){
int id=s[i]-'a';
p=p->Next[id];
if(p==NULL)return 0;
}
return p->flag;
}
void free(trie *t){
if(t==NULL)return;
for(int i=0;i<N;i++)if(t->Next[i])free(t->Next[i]);
delete(t);
}
2.静态空间
例题:洛谷P2580
const int N = 1e6+255;
struct node{
bool rep;
int son[30];
int num;
}t[N];
int cnt=1,n,m;
char s[105];
void insert(char *s){
int now=0;
for(int i=0;s[i];i++){
int ch=s[i]-'a';
if(t[now].son[ch]==0)t[now].son[ch]=cnt++;
now=t[now].son[ch];
t[now].num++;
}
}
int find(char *s){
int now=0;
for(int i=0;s[i];i++){
int ch=s[i]-'a';
if(t[now].son[ch]==0)return 3;
now=t[now].son[ch];
}
if(t[now].num==0)return 3;
if(t[now].rep==0){
t[now].rep=1;
return 1;
}
return 2;
}
3.查询公共前缀的数量
void insert(char str[]){
int len=strlen(str),rt=0;
for(int i=0;i<len;i++){
int cur=str[i]-'a';
if(trie[rt][cur]==0) trie[rt][cur]=++tot;
rt=trie[rt][cur];
num[rt]++;
}
}
int ask(char str[]){
int len=strlen(str),rt=0;
for(int i 0;i<len;i++){
int cur=str[i]-'a';
if(trie[rt][cur]==0) return 0 ;
rt=trie[rt][cur];
}
return num[rt];
}
4.字符串排序(字典序)
void trie_sort(trie *root){
if(!root)return;
if(root->flag){
cout<<root->s<<'\n';
return;
}
for(int i=0;i<26;i++)trie_sort(root->Next[i]);
}
5.维护最长异或路径
例题:洛谷P4551
const int N = 2e6+255;
struct edge{
int v,w,next;
}e[N];
struct trie{
int s[5];
}t[N];
int head[N],cnt=-1,sum[N],tot,n;
void add(int u,int v,int w){
e[++cnt].next=head[u];
e[cnt].v=v;
e[cnt].w=w;
head[u]=cnt;
}
void dfs(int x,int fa){
for(int i=head[x];~i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(v!=fa){
sum[v]=sum[x]^w;
dfs(v,x);
}
}
}
void build(int va,int x){
for(int i=(1<<30);i;i>>=1){
bool c=va&i;
if(!t[x].s[c])t[x].s[c]=++tot;
x=t[x].s[c];
}
}
int find(int va,int x){
int ans=0;
for(int i=(1<<30);i;i>>=1){
bool c=va&i;
if(t[x].s[!c]){
ans+=i;
x=t[x].s[!c];
}else{
x=t[x].s[c];
}
}
return ans;
}
int main(){
memset(head,-1,sizeof(head));cnt=-1;
cin>>n;
for(int i=1,x,y,z;i<n;i++){
cin>>x>>y>>z;
add(x,y,z);
add(y,x,z);
}
dfs(1,-1);
for(int i=1;i<=n;i++)build(sum[i],0);
int ans=0;
for(int i=1;i<=n;i++)ans=max(ans,find(sum[i],0));
cout<<ans;
return 0;
}
6.维护异或和
const int N = 21;
struct trie{
int ch[(N+1)*225][2],w[(N+1)*225],xorv[(N+1)*225],tot;
int mknode(){
++tot;
ch[tot][1]=ch[tot][0]=w[tot]=xorv[tot]=0;
return tot;
}
void maintain(int o){
w[o]=xorv[o]=0;
if(ch[o][0]){
w[o]+=w[ch[o][0]];
xorv[o]^=xorv[ch[o][0]]<<1;
}
if(ch[o][1]){
w[o]+=w[ch[o][1]];
xorv[o]^=(xorv[ch[o][1]]<<1)|(w[ch[o][1]]&1);
}
w[o]&=1;
}
void inserts(int &o,int x,int dp){
if(!o)o=mknode();
if(dp>N)return (void)(w[o]++);
inserts(ch[o][x&1],x>>1,dp+1);
maintain(o);
}
void erase(int o,int x,int dp){
if(dp>20)return (void)(w[o]--);
erase(ch[o][x&1],x>>1,dp+1);
maintain(o);
}
void addall(int o){
swap(ch[o][0],ch[o][1]);
if(ch[o][0])addall(ch[o][0]);
maintain(o);
}
int merge(int a,int b){
if(!a)return b;
if(!b)return a;
w[a]+=w[b];
xorv[a]^=xorv[b];
ch[a][0]=merge(ch[a][0],ch[b][0]);
ch[a][1]=merge(ch[a][1],ch[b][1]);
return a;
}
}t;
7.可持久化字典树(0-1 Trie)
const int N = 325;
struct trie_pst{
int cnt,ch[N*24][2],sum[N*24];
inline int insert(int x,int val){
int o,y;
o=y=++cnt;
for(int i=23;i>=0;i--){
ch[y][0]=ch[x][0];ch[y][1]=ch[x][1];
sum[y]=sum[x]+1;
int tmp=(val&(1<<i))>>i;
x=ch[x][tmp];
ch[y][tmp]=++cnt;
y=ch[y][tmp];
}
sum[y]=sum[x]+1;
return o;
}
inline int query(int l,int r,int val){
int ans=0;
for(int i=23;i>=0;i--){
int c=(val&(1<<i))>>i;
if(sum[ch[r][c^1]]-sum[ch[l][c^1]]){
ans=ans+(1<<i);
r=ch[r][c^1];
l=ch[l][c^1];
}else{
r=ch[r][c];
l=ch[l][c];
}
}
return ans;
}
}trie;
8.0-1 Trie模板
例题:洛谷P4735
#include<bits/stdc++.h>
using namespace std;
const int N = 6e5+100;
int n,m,sum,top;
struct trie_persistent{
int rt[N],sz,ch[2][N<<5],cnt[N<<5],vl[N];
inline void insert(int v){
rt[++top]=++sz;
vl[top]=v;
int l=rt[top-1],r=rt[top];
for(int i=24;i>=0;i--){
int b=((v>>i)&1);
ch[!b][r]=ch[!b][l];
ch[b][r]=++sz;
l=ch[b][l];
r=ch[b][r];
cnt[r]=cnt[l]+1;
}
}
inline int query(int v,int r,int l){
int ans=0;
l=rt[l],r=rt[r];
for(int i=24;i>=0;i--){
int b=((v>>i)&1);
if(cnt[ch[!b][r]]-cnt[ch[!b][l]])ans+=(1<<i),b=!b;
l=ch[b][l];
r=ch[b][r];
}
return ans;
}
}trie;
char op[10];
int main(){
cin>>n>>m;
trie.insert(0);
for(int i=1,x;i<=n;i++){
cin>>x;
sum^=x;
trie.insert(sum);
}
for(int i=1,x,l,r;i<=m;i++){
cin>>op;
switch(op[0]){
case 'A':
cin>>x;
sum^=x;
trie.insert(sum);
break;
case 'Q':
cin>>l>>r>>x;
printf("%d\n",trie.query(x^sum,r,l-1));
break;
}
}
return 0;
}

浙公网安备 33010602011771号