Trie树

就是把字符串转变成一个树,每个节点连接下一个字符,用空间换时间。

对于区分大小写或不区分的题目,只需要改变ch[][26]的值就行了。

ch[u][x]表示u节点(标号决定)下一个x字符节点的标号。

如果题目让记录附加值,那就用val[标号]在插入时记录一下就好了。

复制代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2333;
struct trie{
    ll ch[maxn][26],siz,val[maxn];
    trie(){
        siz=1;//一开始的时候只有根节点这一个节点 
        memset(ch[0],0,sizeof(ch[0]));
        memset(val,0,sizeof(val));
    }
    inline ll idx(char c){return c-'a';}
    void insert(char *s,ll v)
    {
        ll u=0,len=strlen(s+1);
        for(ll i=1;i<=len;i++){
            ll c=idx(s[i]);
            if(!ch[u][c]){
                memset(ch[siz],0,sizeof ch[siz]);
                val[siz]=0;
                ch[u][c]=siz++;
            } 
            u=ch[u][c];
        }
        val[u]=v;
    }
    ll query(char *s)
    {
        ll u=0,len=strlen(s+1);
        for(ll i=1;i<=len;i++){
            ll c=idx(s[i]);
            if(!ch[u][c])return -1;
            u=ch[u][c];
        }
        return val[u];
    }
}tr;
int main()
{
    return 0;
}
复制代码

P2580 于是他错误的点名开始了

(名字好奇怪)

复制代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10005*50;
int n;
struct trie
{
    int cnt,ch[maxn][26];
    int vis[maxn];
    trie()
    {
        cnt=1;
        memset(ch[0],0,sizeof ch[0]);
        memset(vis,0,sizeof vis);
    }
    inline int ex(char c){return c-'a';}
    inline void insert(char *s)
    {
        int u=0,len=strlen(s+1);
        for(int i=1;i<=len;i++)
        {
            int c=ex(s[i]);
            if(!ch[u][c]){
                memset(ch[cnt],0,sizeof ch[cnt]);
                ch[u][c]=cnt++;
            }
            u=ch[u][c];
        }
    }
    inline int query(char *s)
    {
        int u=0,len=strlen(s+1);
        for(int i=1;i<=len;i++)
        {
            int c=ex(s[i]);
            if(!ch[u][c])return 2;
            u=ch[u][c];
        }
        if(!vis[u]){
            vis[u]++;return 1;
        }
        return 3;
    }
}tr;
int main()
{
    scanf("%d",&n);
    char a[100];
    for(int i=1;i<=n;i++)
    {
        scanf("%s",a+1);
        tr.insert(a);
    }
    int m;
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",a+1);
        switch(tr.query(a))
        {
            case(1):{
                printf("OK\n");
                break;
            } 
            case(2):{
                printf("WRONG\n");
                break;
            }
            case(3):{
                printf("REPEAT\n");
                break;
            }
        }
    }
    return 0;
}
复制代码

 

posted @   Star_Cried  阅读(156)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示