知识概览
- Trie:高效地存储和查找字符串集合的数据结构
- 数字、汉字可以用二进制位来存
例题展示
题目链接
Trie字符串统计:
https://www.acwing.com/problem/content/837/
代码
#include <cstdio>const int N = 100010;int son[N][26], cnt[N], idx; // 下标是0的点,既是根节点,又是空节点
char str[N];void insert(char str[])
{int p = 0;for (int i = 0; str[i]; i++){int u = str[i] - 'a';if (!son[p][u]) son[p][u] = ++idx;p = son[p][u];}cnt[p]++;
}int query(char str[])
{int p = 0;for (int i = 0; str[i]; i++){int u = str[i] - 'a';if (!son[p][u]) return 0;p = son[p][u];}return cnt[p];
}int main()
{int n;scanf("%d", &n);while (n--){char op[2];scanf("%s%s", op, str);if (op[0] == 'I') insert(str);else printf("%d\n", query(str));}return 0;
}
题目链接
最大异或对:
https://www.acwing.com/problem/content/145/
题解
对于每个数,先插入,然后再找和这个数异或最大的数,找的方法是找已存储在字典树的数,从高位到低位,尽量找和当前数该位不同的数。最终得到的数即为所求。
代码
#include <cstdio>
#include <algorithm>using namespace std;const int N = 100010, M = 31 * N;int n;
int son[M][2], idx, x;void insert(int x)
{int p = 0;for (int i = 30; i >= 0; i--){int u = x >> i & 1;if (!son[p][u]) son[p][u] = ++idx;p = son[p][u];}
}int query(int x)
{int p = 0, res = 0;for (int i = 30; i >= 0; i--){int u = x >> i & 1;if (son[p][!u]){p = son[p][!u];res = res * 2 + !u;}else{p = son[p][u];res = res * 2 + u;}}return res;
}int main()
{scanf("%d", &n);int res = 0;for (int i = 0; i < n; i++){scanf("%d", &x);insert(x);int t = query(x);res = max(res, x ^ t);}printf("%d\n", res);return 0;
}