#板子 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;
}
posted @ 2025-06-12 22:08  chhhcooh  阅读(2)  评论(0)    收藏  举报