1.前缀统计
题目链接
题解:对n个字符串建立trie,然后对于每一个询问都由浅到深度变量trie即可,线性的复杂度
代码:
#include<iostream>
using namespace std;
const int N=1000010,M=500000;
int n,m;
int son[M][26],cnt[N],idx;
char str[N];
void insert()//建立trie
{
int p=0;
for(int i=0;str[i];i++)
{
int &s=son[p][str[i]-'a'];
if(!s) s=++idx;//如果该节点不存在,就要建立该节点
p=s;
}
cnt[p]++;//统计p号节点结尾单词的个数
}
int query()//查询
{
int p=0,res=0;
for(int i=0;str[i];i++)
{
int &s=son[p][str[i]-'a'];
if(!s)break;//已经找到末尾
p=s;
res+=cnt[p];
}
return res;
}
int main()
{
cin>>n>>m;
while (n--)
{
scanf("%s",str);
insert();
}
while (m--)
{
scanf("%s",str);
printf("%d\n",query());
}
}
2.The XOR Largest Pair
思路:
根据二进制,将每个数都加入trie中,然后遍历遍历每一个数,同时遍历trie,使其尽可能每一位都不同
代码:
#include <iostream>
#include <math.h>
using namespace std;
const int N = 100010, M = 3100010;
int n;
int son[M][2], idx;
int a[N];
void insert(int x)//插入
{
int p = 0;
for (int i = 30; ~i; i--)
{
int &s = son[p][x >> i & 1];
if (!s)
s=++idx;
p = s;
}
}
int query(int x)
{
int res = 0, p = 0;
for (int i = 30; ~i; i--)
{
int s = x >> i & 1;
if (son[p][!s])//与x第i位不同的数存在
{
res += 1 << i;
p = son[p][!s];
}
else不存在
{
p = son[p][s];
}
}
return res;
}
int main()
{
cin >> n;
int res=0;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
insert(a[i]);
}
for (int i = 1; i <= n; i++)
res = max(res, query(a[i]));
cout << res << endl;
}
3.The xor-longest Path
题目链接
题目大意:给一棵树,数上每个点都有一个编号,每条边都有对应的权值,我们需要找出2个点,使得2个点之间各边权值的异或合最大
题解:
假设存在如上的一棵树,我们需要计算1号点和2号点之间的异或值也就是 v 1 v_1 v1^ v 2 v_2 v2,我们可以转化为 v 1 ∧ v 3 ∧ v 3 ∧ v 2 v_1\wedge v_3\wedge v_3\wedge v_2 v1∧v3∧v3∧v2,也就是 v 1 v_1 v1到根节点的异或值 异或上 v 2 v_2 v2到根节点的异或值。我们只需要预处理好每个点到根节点的异或值,这一题也就转换成了第二题
代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010, M = 200010;
int n;
int h[N], e[M], c[M], ne[M], cnt;
int a[N], son[3000000][2], idx;
void add(int u, int v, int w)
{
e[cnt] = v, c[cnt] = w, ne[cnt] = h[u], h[u] = cnt ++ ;
}
void dfs(int u, int father, int sum)
{
a[u] = sum;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j != father) dfs(j, u, sum ^ c[i]);
}
}
void insert(int x)
{
int p = 0;
for (int i = 30; i >= 0; i -- )
{
int &s = son[p][x >> i & 1];
if (!s) s = ++ idx;
p = s;
}
}
int search(int x)
{
int p = 0, res = 0;
for (int i = 30; i >= 0; i -- )
{
int s = x >> i & 1;
if (son[p][!s])
{
res += 1 << i;
p = son[p][!s];
}
else p = son[p][s];
}
return res;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n;
for (int i = 0; i < n - 1; i ++ )
{
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
add(v, u, w);
}
dfs(0, -1, 0);
for (int i = 0; i < n; i ++ ) insert(a[i]);
int res = 0;
for (int i = 0; i < n; i ++ ) res = max(res, search(a[i]));
cout << res << endl;
return 0;
}