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
扫描二维码关注公众号,回复:
171338 查看本文章
#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; }