835. Trie字符串统计
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
char str[N];
int son[N][26], cnt[N], idx;
// 0号点既是根节点
// son[][]存储树中每个节点的子节点
// cnt[]存储以每个节点结尾的单词数量,以当前结点为结尾的单词有多少个
//idx是我们当前用的是哪个下标
// 插入一个字符串
void Insert(char *str)
{
int p = 0;//当前结点为根节点
for (int i = 0; str[i]; i ++ )
{
int u = str[i] - 'a';//将要插入的a-z映射成0-25
if (!son[p][u]) son[p][u] = ++ idx;//如果当前结点不存在u这个儿子结点,就创建出这个儿子结点
p = son[p][u];//令儿子结点为当前结点
}
cnt[p] ++ ;//字符串个数加1
}
// 查询字符串出现的次数
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];//返回以p结尾的单词数量
}
int main()
{
int n;
cin>>n;
while(n--)
{
char c;
scanf(" %c %s",&c,str);
if(c=='I')Insert(str);
else
{
printf("%d\n",query(str));
}
}
return 0;
}//&&(k==0||k==4||l==0||l==4||r==0||r==4)
//5min
1471:【例题1】Phone List
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int tree[N][10];
int sum[N];
int cnt=0;
void Insert(char s[])
{
int root = 0;
for(int i=0;s[i];i++)
{
int id = s[i]-'0';
if(!tree[root][id])tree[root][id]=++cnt;
root = tree[root][id];
sum[root]++;
}
}
int Search(char s[])
{
int root = 0;
for(int i = 0;s[i];i++)
{
int id = s[i]-'0';
if(!tree[root][id])return 0;
root = tree[root][id];
}
return sum[root];
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n;
cnt = 0;
memset(tree,0,sizeof(tree));
memset(sum,0,sizeof(sum));
char s[10005][15];
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s[i];
Insert(s[i]);
}
int flag=0;
for(int i=0;i<n;i++)
{
flag= max(flag,Search(s[i]));
}
if(flag<2)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
1472:【例题2】The XOR Largest Pair
板子题
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
/*
第一维的大小是绝对位置,绝对位置的话是数的个数乘以位数,
第一位的大小等于树的结点个数,结点个数跟数的个数以及这个数的长度有关
*/
int tree[32*N][2];
int sum[32*N];
int cnt=0;
void Insert(int s)
{
int root = 0;
for(int i=31;i>=0;i--)
{
int id = 1&(s>>i);
if(!tree[root][id])tree[root][id]=++cnt;
root = tree[root][id];
sum[root]++;
}
}
int Search(int s)
{
int root = 0;
int ans=0;
for(int i = 31;i>=0;i--)
{
int id = 1&(s>>i);
if(tree[root][!id])
{
ans+=(1<<i);
root=tree[root][!id];
}
else
root = tree[root][id];
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int n;
cnt = 0;
memset(tree,0,sizeof(tree));
memset(sum,0,sizeof(sum));
int s[100005];
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s[i];
Insert(s[i]);
}
int ans=0;
for(int i=0;i<n;i++)
ans=max(ans,Search(s[i]));
cout<<ans<<endl;
return 0;
}
1478:The xor-longest Path
描述:原题来自:POJ 3764
给定一棵 n 个点的带权树,求树上最长的异或和路径。
思路:异或和路径(u,v)可以转换为f(1,u)^f(1,v),那么我们就可以以节点1为跟搜索遍历到每一个节点的异或和路径,放到数组里,这样就转化为,在一个数组里,取两个数异或,得到的数最大是多少,刚好这是模板题,就可以做了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
/*
第一维的大小是绝对位置,绝对位置的话是数的个数乘以位数,
第一位的大小等于树的结点个数,结点个数跟数的个数以及这个数的长度有关
*/
int tree[32*N][2];
int a[N],vis[N];
int sum[32*N];
int cnt=0;
void Insert(int s)
{
int root = 0;
for(int i=30;i>=0;i--)
{
int id = 1&(s>>i);
if(!tree[root][id])tree[root][id]=++cnt;
root = tree[root][id];
sum[root]++;
}
}
int Search(int s)
{
int root = 0;
int ans=0;
for(int i=30;i>=0;i--)
{
int id = 1&(s>>i);
if(tree[root][!id])
{
root=tree[root][!id];
ans|=(1<<i);
}
else
{
root=tree[root][id];
}
}
//cout<<"ans="<<ans<<endl;
//cout<<"sum1="<<sum1[root]<<endl;
return ans;
}
int head[N];
struct edge
{
int w,to,next;
}e[N*2];//定义边的三个信息,w表示边权,to表示边的终点,next表示上一条边
void add(int x,int y,int z)//链式前向星存边
{
e[cnt].to=y;
e[cnt].w=z;
e[cnt].next=head[x];//next表示以x为起点的上一条边的编号
head[x]=cnt++;//head[x]表示以x为起点的最后一条边的编号
}
void dfs(int u,int w)
{
a[u]=w;
vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(!vis[v])
{
dfs(v,w^e[i].w);
}
}
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int n;
cin>>n;
memset(head,-1,sizeof(head));
for(int i=0;i<n-1;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x-1,y-1,z);
add(y-1,x-1,z);
}
dfs(0,0);
/*for(int i=0;i<n;i++)
cout<<a[i]<<" ";*/
//cout<<endl;
cnt=0;
for(int i=0;i<n;i++)
{
Insert(a[i]);
}
int ma=0;
for(int i=0;i<n;i++)
{
ma=max(ma,Search(a[i]));
}
cout<<ma<<endl;
return 0;
}
Xor sum
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
/*
第一维的大小是绝对位置,绝对位置的话是数的个数乘以位数,
第一位的大小等于树的结点个数,结点个数跟数的个数以及这个数的长度有关
*/
int tree[15*N][2];
int sum[15*N];
int cnt=0,k;
void Insert(int s,int index)
{
int root = 0;
for(int i=31;i>=0;i--)
{
int id = 1&(s>>i);
if(!tree[root][id])tree[root][id]=++cnt;
root = tree[root][id];
if(sum[root]!=0)
sum[root]=min(sum[root],index);
else sum[root]=index;
}
}
int Search(int s)
{
int root = 0;
int ans=0;
for(int i = 31;i>=0;i--)
{
int id = 1&(s>>i);
if(tree[root][!id])
{
ans+=(1<<i);
root=tree[root][!id];
}
else
root = tree[root][id];
if(ans>=k)
{
return sum[root];
}
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n;
cnt = 0;
memset(tree,0,sizeof(tree));
//memset(sum,0,sizeof(sum));
int a[100005],s[100005];
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]^a[i];
Insert(s[i],i);
}
int mi=999999999;
int l,r;
int flag=0;
for(int i=0;i<=n;i++)
{
int t=Search(s[i]);
if(t!=-1)
{
flag=1;
if(abs(i-t)<mi)
{
mi=min(mi,abs(i-t));
l=i+1;
r=t;
}
}
}
if(flag)
cout<<l<< " "<<r<<endl;
else cout<<-1<<endl;
for(int i=0;i<=cnt;i++)
sum[i]=0;
}
return 0;
}