Acwing 142. 前缀统计
题目
算法分析
详见 这篇文章
C++ Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define rg register
typedef long long ll;
using namespace std;
inline int sread()
{
int x=0,f=1;char c=getchar();
while(c>'9'||c<'0') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return f*x;
}
const int maxn=1000010;
int trie[maxn][26],tail[maxn],tot=0;
int n,m,len;
char c[maxn];
void _insert(char c[])
{
int p=0;
for(rg int i=0;i<len;++i)
{
int ch=c[i]-'a';
if(trie[p][ch]==0) trie[p][ch]= ++tot;
p=trie[p][ch];
}
tail[p]++;
}
int _search(char c[])
{
int p=0,ans=0;
for(int i=0;i<len;++i)
{
p=trie[p][c[i]-'a'];
if(p==0) return ans;
ans+=tail[p];
}
return ans;
}
int main()
{
n=sread();
m=sread();
for(rg int i=1;i<=n;++i)
{
len=0;
while((c[len]=getchar())!='\n') len++;
_insert(c);
}
for(rg int i=1;i<=m;++i)
{
len=0;
while((c[len]=getchar())!='\n') len++;
int ans= _search(c);
printf("%d\n",ans);
}
return 0;
}
Acwing 143. 最大异或对
题目
算法分析
在检索字典树的过程中,每一次都尝试沿着与当前位相反的指针向下询问,若无则向下询问即可。
C++ Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define rg register
typedef long long ll;
using namespace std;
inline int sread()
{
int x=0,f=1;char c=getchar();
while(c>'9'||c<'0') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return f*x;
}
const int maxn=1000010;
int trie[10*maxn][3],tot=0;
int n,m,a[maxn],ans;
void _insert(int x)
{
int p=0;
for(rg int i=31;i>=0;i--)
{
int ch=x>>i&1;
if(trie[p][ch]==0) trie[p][ch]= ++tot;
p=trie[p][ch];
}
}
int _search(int x)
{
int p=0,ans=0;
for(int i=31;i>=0;i--)
{
int ch=x>>i&1;
if(trie[p][!ch]!=0) //存在相反的
{
p=trie[p][!ch];
ans=ans*2+1;//相当于左移一位再加 1
}
else
{
p=trie[p][ch];
ans=ans*2;//仅左移一位
}
}
return ans;
}
int maxx(int a,int b)
{
return a>b?a:b;
}
int main()
{
n=sread();
for(rg int i=1;i<=n;++i)
{
a[i]=sread();
_insert(a[i]);
}
for(rg int i=1;i<=n;++i)
{
ans=maxx(ans,_search(a[i]));
}
printf("%d\n",ans);
return 0;
}
在此之外还学习了可持续化Trie,详细讲解可见 这篇文章