#板子 trie树
概述
字典树就是一颗多叉树 根节点为空 其余节点表示一个字符 而一条从根节点开始的路径可以表示一个字符串
基本操作
插入字符串
void insert(string s)
{
int p=0;//从根节点开始 p初始化为0(根节点编号为0
for(int i=0;i<s.size();i++)
{
int idx=s[i]-'a';
if (tree[p][idx]==0)//若不存在子节点
{
temp++;//编号+1
tree[p][idx]=temp;//创建一个新的节点
}
p=tree[p][idx];//从这个节点继续往下走
}
cnt[p]++;//以p点结尾的字符串数量+1
}
查找一个字符串是否存在
int query(string s)
{
int p=0;
for(int i=0;i<s.size();i++)
{
if (tree[p][s[i]-'a']==0)//找不到s[i-1]到s[i]的路
return 0;//直接返回
p=tree[p][s[i]-'a'];//继续往下走
}
return cnt[p];
}
例题
https://www.luogu.com.cn/problem/P1481
直接建字典树 然后丢进去dfs 计算一条路径上cnt值的和的最大值
#include "bits/stdc++.h"
#define ll long long
//#define int long long
#define orz main
#define pb push_back
using namespace std;
ll N=2e5;
ll max0=0;
vector<int> cnt(N);//cnt表示以某个节点为结尾的字符串的数量
vector<vector<int>> tree(N,vector<int>(26));
ll temp=0;//temp为节点编号
void insert(string s)
{
int p=0;//从根节点开始 p初始化为0(根节点编号为0
for(int i=0;i<s.size();i++)
{
int idx=s[i]-'a';
if (tree[p][idx]==0)//若不存在子节点
{
temp++;//编号+1
tree[p][idx]=temp;//创建一个新的节点
}
p=tree[p][idx];//从这个节点继续往下走
}
cnt[p]++;//以p点结尾的字符串数量+1
}
void dfs(ll step,int node )
{
for (int i=0;i<26;i++)
if (tree[node][i]!=0)
dfs(step+cnt[tree[node][i]],tree[node][i]);
max0=max(max0,step);//更新最长字符串链
}
void QAQ()
{
ll n;
cin>>n;
vector<string> s(n);
for(int i=0;i<n;i++)
{
cin>>s[i];
insert(s[i]);
}
dfs(0,0);
cout<<max0<<endl;
return ;
}
signed orz()
{
ll ___=1;
//cin>>___;
while (___--)
QAQ();
return 0;
}
https://codeforces.com/gym/105941
2025郑州邀请赛e
贪心思想为将字符串按字典序排序后 相邻的字符串拿来匹配 这样最优
直接sort 然后奇数字符串丢进去建树 偶数字符串查询出匹配得到的值加起来就可以了
#include "bits/stdc++.h"
#define ll long long
#define int long long
#define orz main
#define pb push_back
using namespace std;
ll N=2e5;
ll max0=0;
vector<int> cnt(N+10);//cnt表示以某个节点为结尾的字符串的数量
vector< vector<int> > tree(N,vector<int>(26));
ll temp=0;//temp为节点编号
void insert(string s)
{
int p=0;//从根节点开始 p初始化为0(根节点编号为0
for(int i=0;i<s.size();i++)
{
int idx=s[i]-'a';
if (tree[p][idx]==0)//若不存在子节点
{
temp++;//编号+1
tree[p][idx]=temp;//创建一个新的节点
}
cnt[tree[p][idx]]++;
p=tree[p][idx];
}
}
ll query(string s)
{
int p=0;
ll sum=0;
for(int i=0;i<s.size();i++)
{
if (tree[p][s[i]-'a']==0)//找不到s[i-1]到s[i]的路
return sum;//直接返回
sum+=cnt[tree[p][s[i]-'a']];
p=tree[p][s[i]-'a'];//继续往下走
}
return sum;
}
void QAQ()
{
ll n;
cin>>n;
vector<string> s(2*n);
for(int i=0;i<2*n;i++)
cin>>s[i];
sort(s.begin(),s.end());
for(int i=0;i<2*n;i++)
if (i%2==0)
insert(s[i]);
ll ans=0;
for (int i=0;i<2*n;i++)
if (i%2==1)
ans+=query(s[i]);
cout<<ans<<endl;
}
signed orz()
{
ll ___=1;
//cin>>___;
while (___--)
QAQ();
return 0;
}