0.1 字典樹
功能:
在數組中找與一個數異或值最大的元素。
支持添加,刪除操作,查找操作。
例如:hdu4825
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <ctype.h>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX = 35*1e5+5;
ll a[MAX];
int root,tot,Next[MAX][2],cnt[MAX];
ll End[MAX];
int Newnode()
{
memset(Next[tot],-1,sizeof(Next[tot]));
cnt[tot] = 0;
End[tot] = 0;
return tot ++;
}
void Init()
{
tot = 0;
root = Newnode();
}
void Insert(ll x)
{
int p = root;
cnt[p] ++;
for(int i = 32; i >= 0; i--)
{
int idx = ((1LL<<i)&x) ? 1 : 0;
if(Next[p][idx] == -1)
{
Next[p][idx] = Newnode();
}
p = Next[p][idx];
cnt[p] ++;
}
End[p] = x;
}
void Del(ll x)
{
int p = root;
cnt[p]--;
for(int i = 32; i>=0 ; i--)
{
int idx = ((1LL<<i)&x)?1:0;
p = Next[p][idx];
cnt[p]--;
}
}
ll Search(ll x)
{
int p = root;
for(int i = 32; i>=0 ; i--)
{
int idx = ((1LL<<i)&x)?1:0;
if(idx == 0)
{
if(Next[p][1] != -1 && cnt[Next[p][1]])
p = Next[p][1];
else
p = Next[p][0];
}
else
{
if(Next[p][0] != -1 && cnt[Next[p][0]])
p = Next[p][0];
else
p = Next[p][1];
}
}
return End[p];
}
int main()
{
int t;
scanf("%d",&t);
int cas = 1;
while(t--)
{
Init();
int n,m,ma = 0;
scanf("%d%d",&n,&m);
for(int i = 0; i < n; i++)
{
scanf("%lld",&a[i]);
Insert(a[i]);
}
printf("Case #%d:\n",cas++);
while(m--)
{
ll x;
scanf("%lld",&x);
int ans = Search(x);
printf("%d\n",ans);
}
}
return 0;
}
單詞字典樹
輸入n個單詞,m個查詢,求查詢的單詞是否出現,幾次,或者是否以前綴形式出現
數據量小也可用map 解決
如https://qduoj.com/problem/2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <ctype.h>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX = 100*1e3+5; // 每個數分32個..
int root,tot,Next[MAX][30],cnt[MAX];
int Newnode()
{
memset(Next[tot],-1,sizeof(Next[tot]));
cnt[tot] = 0;
return tot ++;
}
void Init()
{
tot = 0;
root = Newnode();
}
int getid(char ch)
{
if(ch == '*') return 26;
if(ch == '?') return 27;
return ch-'a';
}
int isover(char s[])
{
for(int i = 0; s[i]; i++)
if(s[i] != '*') return 0;
return 1;
}
void Insert(int p,char s[])
{
if(s[0] == 0)
{
cnt[p] = 1;
return;
}
int id = getid(s[0]);
if(Next[p][id] == -1)
{
Next[p][id] = Newnode();
}
if(isover(s)) cnt[p] = 1;
Insert(Next[p][id],s+1);
}
int Search(int p,char s[])
{
if(s[0] == 0)
{
return cnt[p] != 0;
}
int id = getid(s[0]);
if(Next[p][id] != -1)
{
if(Search(Next[p][id],s+1)) return 1;
}
if(Next[p][27] != -1)
{
if(Search(Next[p][27],s+1)) return 1;
}
if(Next[p][26] != -1)
{
int len = strlen(s);
for(int i = 0; i <= len; i++)
{
if(Search(Next[p][26],s+i)) return 1;
}
}
return 0;
}
char s[1005];
int main()
{
int t;
scanf("%d",&t);
int cas = 1;
while(t--)
{
int n,m;
Init();
scanf("%d%d",&n,&m);
for(int i = 0;i < n; i++)
{
scanf("%s",s);
Insert(root,s);
}
printf("Case #%d:\n",cas++);
for(int i = 0; i < m ;i++)
{
int yes;
scanf("%s",s);
yes = Search(root,s);
printf("%d",yes);
}
puts("");
}
return 0;
}
再比如hdu2846後綴字典樹,查詢的是某單詞是字典中幾個單詞的子串,,後綴加排除重複,如果問的是子串出現的·次數,就不用排重
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <ctype.h>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX = 25*1e5+5;
int root,tot,Next[MAX][30],cnt[MAX],of[MAX];
int Newnode()
{
memset(Next[tot],-1,sizeof(Next[tot]));
cnt[tot] = 0;
of[tot] = 0;
return tot ++;
}
void Init()
{
tot = 0;
root = Newnode();
}
int getid(char ch)
{
return ch-'a';
}
void Insert(int p,char s[],int cur)
{
if(s[0] == 0)
{
if(of[p] != cur)
{
cnt[p]++;
of[p] = cur;
}
return;
}
int id = getid(s[0]);
if(Next[p][id] == -1)
{
Next[p][id] = Newnode();
}
if(of[p] != cur) // 防止字典中的一個單詞重複記錄某個子串
{
cnt[p]++;
of[p] = cur;
}
Insert(Next[p][id],s+1,cur);
}
int Search(int p,char s[])
{
if(s[0] == 0)
{
return cnt[p];
}
int id = getid(s[0]);
if(Next[p][id] != -1)
{
return Search(Next[p][id],s+1);
}
return 0;
}
char s[1005];
char str[1005];
map <string,bool> mp;
int main()
{
int n;
scanf("%d",&n);
Init();
for(int i = 1; i <= n; i++)
{
scanf("%s",s);
for(int j = 0; s[j]; j++)
{
Insert(root,s+j,i);
}
}
int m;
scanf("%d",&m);
while(m--)
{
scanf("%s",s);
printf("%d\n",Search(root,s));
}
return 0;
}
hdu 1305 求給定字符串數組某個元素是否是某個其它元素的前綴,,保存所有前綴,查詢每個單詞,看出現次數是否均爲1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <ctype.h>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX = 25*1e5+5;
int root,tot,Next[MAX][3],cnt[MAX];
int Newnode()
{
memset(Next[tot],-1,sizeof(Next[tot]));
cnt[tot] = 0;
return tot ++;
}
void Init()
{
tot = 0;
root = Newnode();
}
int getid(char ch)
{
return ch-'0';
}
void Insert(int p,char s[])
{
if(s[0] == 0)
{
cnt[p]++;
return;
}
int id = getid(s[0]);
if(Next[p][id] == -1)
{
Next[p][id] = Newnode();
}
cnt[p] ++;
Insert(Next[p][id],s+1);
}
int Search(int p,char s[])
{
if(s[0] == 0)
{
return cnt[p];
}
int id = getid(s[0]);
if(Next[p][id] != -1)
{
return Search(Next[p][id],s+1);
}
return 0;
}
char s[10005][20];
int main()
{
int k = 0;
int cas = 1;
Init();
while(scanf("%s",s[k])!=EOF)
{
if(!strcmp(s[k],"9"))
{
int yes = 1;
for(int i = 0; i < k; i++)
{
// puts(s[i]);
/// cout <<Search(root,s[i]) <<endl;
if(Search(root,s[i]) >= 2)
{
yes = 0;
break;
}
}
if(yes) printf("Set %d is immediately decodable\n",cas++);
else printf("Set %d is not immediately decodable\n",cas++);
Init();
k = 0;
}
else
{
Insert(root,s[k++]);
}
}
return 0;
}
這個可以先把單詞存好,逐個查詢,枚舉分點,注意一個單詞可以有 兩個一樣的單詞組成,,,如 aa 這種情況,如過數組有一個a就可以了.......
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <ctype.h>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX = 25*1e5+5;
int root,tot,Next[MAX][30],cnt[MAX];
int Newnode()
{
memset(Next[tot],-1,sizeof(Next[tot]));
cnt[tot] = 0;
return tot ++;
}
void Init()
{
tot = 0;
root = Newnode();
}
int getid(char ch)
{
return ch-'a';
}
void Insert(int p,char s[])
{
if(s[0] == 0)
{
cnt[p]++;
return;
}
int id = getid(s[0]);
if(Next[p][id] == -1)
{
Next[p][id] = Newnode();
}
Insert(Next[p][id],s+1);
}
int Search(int p,char s[])
{
if(s[0] == 0)
{
return cnt[p];
}
int id = getid(s[0]);
if(Next[p][id] != -1)
{
return Search(Next[p][id],s+1);
}
return 0;
}
char s[50005][500];
char str[500];
int main()
{
int k = 0;
Init();
while(scanf("%s",s[k])!=EOF)
{
Insert(root,s[k]);
k++;
}
for(int i = 0; i < k; i++)
{
int len = strlen(s[i]);
for(int j = 0; j < len-1; j++)
{
str[j] = s[i][j];
str[j+1] = 0;
if(Search(root,str) >= 1 && Search(root,&s[i][j+1]) >= 1)
{
puts(s[i]);
break;
}
}
}
return 0;
}