字符串统计
法一:Trie树
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int son[N][26];
int cnt[N];
int idx;
int n;
void insert(string s)
{
int p=0;
for (int i=0;i<s.size();i++)
{
int u = s[i]-'a';
if (!son[p][u]) son[p][u] = ++idx;
p=son[p][u];
}
cnt[p]++;
}
int query(string s)
{
int p = 0;
for (int i=0;i<s.size();i++)
{
int u = s[i]-'a';
if (!son[p][u]) return 0;
p=son[p][u];
}
return cnt[p];
}
int main()
{
scanf("%d",&n);
while (n--)
{
string ch,s;
cin>>ch>>s;
if (ch[0]=='I') insert(s);
else printf("%d\n",query(s));
}
return 0;
}
法二:哈希表干就完了
#include <bits/stdc++.h>
using namespace std;
unordered_map<string,int>S;
int n;
int main()
{
cin>>n;
while (n--)
{
string ch,s;
cin>>ch>>s;
if (ch[0]=='I') S[s]++;
else cout<<S[s]<<endl;
}
return 0;
}
最大异或对
字典树应用的绝对好题,收获满满~
最直观的想法,暴力就完事儿了(肯定TLE,O(n2))
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N];
int n;
int main()
{
scanf("%d",&n);
for (int i=0;i<n;i++) scanf("%d",&a[i]);
int ans = 0;
for (int i=0;i<n;i++)
{
for (int j=0;j<i;j++)
ans = max(ans,a[i]^a[j]);
}
printf("%d\n",ans);
return 0;
}
字典树上了,思路清晰,代码逻辑也很清晰
我们分析发现,要想优化两重循环的暴力,第一层没法再优化了,必须要枚举一遍
那就是优化内层遍历的情况,也就是快速得到与当前枚举的数异或最大的数字是哪个数
#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = 31*N;
int a[N];
int idx;
int son[M][2];
int n;
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 res=0;
int p = 0;
for (int i=30;i>=0;i--)
{
int u =x>>i&1;
if (son[p][!u])
{
p=son[p][!u];
res = (res<<1)+!u;
}
else
{
p=son[p][u];
res=(res<<1)+u;
}
}
return res;
}
int main()
{
scanf("%d",&n);
for (int i=0;i<n;i++) scanf("%d",&a[i]);
int ans = 0;
for (int i=0;i<n;i++)
{
insert(a[i]);
int t = query(a[i]);
ans = max(ans,a[i]^t);
}
printf("%d\n",ans);
return 0;
}
前缀统计
模板题的应用
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010,M = 2*100010;
int son[N][26];
int cnt[M];
int n,m;
int idx;
void insert(string s)
{
int p =0;
for (int i=0;i<s.size();i++)
{
int u = s[i]-'a';
if (!son[p][u]) son[p][u]=++idx;
p=son[p][u];
}
cnt[p]++;
}
int query(string s)
{
int p = 0;
int ans = 0;
for (int i=0;i<s.size();i++)
{
int u = s[i]-'a';
p=son[p][u];
if (p==0) return ans;
ans+=cnt[p];
}
return ans;
}
int main()
{
cin>>n>>m;
while (n--)
{
string s;
cin>>s;
insert(s);
}
while (m--)
{
string s;
cin>>s;
cout<<query(s)<<endl;
}
return 0;
}