训练指南 第3章 使用数据结构 3.3.1字符串 Trie (大白书)

3.3 字符串

3.3.1Trie(前缀树)

数组(好写)

#include <iostream>
#include <cstring>
using namespace std;
const int maxnode=1e5+10;///最多有多少层
const int sigma_size=26;///字母的话就是26
struct Trie{
    int ch[maxnode][sigma_size];///ch[u][0]代表这个结点不存在
    int val[maxnode];///结点的权值(相当于标记是否为一个字符串的最后一个元素)
    int sz;///结点总数
    Tire(){sz=1; memset(ch[0],0,sizeof(ch[0])); }///初始化第一个根结点
    int idx(char c){return c-'a';}
    //
    ///插入字符串s,附加信息v(权值)。注意v必须非0,因为0代表“本结点不是单词结点”
    void insert(char *s, int v){
        int u=0, len=strlen(s);
        for(int i=0; i<len; i++){
            int c=idx(s[i]);
            if(!ch[u][c]){///结点不存在
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;///中间结点的附加信息为0.
                ch[u][c]=sz++;///新建结点
            }
            u=ch[u][c];///往下走。
        }
        val[u]=v;///最后一个字符的附加信息为v。
    }
    int find(char *s){
        int u=0, len=strlen(s);
        for(int i=0; i<len; i++){
            int c=idx(s[i]);
            if(!ch[u][c])return false;
            u=ch[u][c];
        }
        return val[u];
    }
    bool del(char *s){
        int u=0,len=strlen(s);
        for(int i=0; i<len; i++){
            int c=idx(s[i]);
            if(!ch[u][c])return false;///找不到这个孩子。
            u=ch[u][c];
        }
        if(val[u]==0)return false;///不存在以当前结点结尾的字符串
        val[u]=0;///把这一个结点标记为0,表示删去这一个字符串。
        return true;
    }
};
int main()
{
    return 0;
}

指针(没debug过。。。。。误用)

#include <iostream>
#include <cstring>
#include <cstdio>
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(int i=(x); i<=(y); i++)
using namespace std;
const int sigma_size=26;
struct node{
    int num;///记录当前结点,有多少个字符串结尾。
    node *next[sigma_size];
    node(){
        num=0;///记录以该结点结尾的字符数。
        mst(next,NULL);///初始化,该结点所有指向儿子的指针。
    }
}*root;
int idx(char c){return c-'a';}
void insert(node* u, char*s){
    int len=strlen(s);
    node *p=u;
    for(int i=0; i<len; i++){
        int k=idx(s[i]);
        if(p->next[k]==NULL)p->next[k]=new node();///当前结点不存在,就new 一个新结点。
        p=p->next[k];///指向儿子
    }
    p->num++;///标记尾结点
}
bool find(node *u, char *s){
    int len=strlen(s);
    node *p=u;
    for(int i=0; i<len; i++){
        int k=idx(s[i]);
        if(p->next[k]==NULL)return false;///当前结点不存在
        p=p->next[k];///指向儿子
    }
    return p->num;///查看是否有该结点结尾的字符串。
}
bool del(node*u, char *s){
    int len=strlen(s);
    node *p=u;
    for(int i=0; i<len; i++){
        int k=idx(s[i]);
        if(p->next[k]==NULL)return false;///当前结点不存在
        p=p->next[k];
    }
    if(p->num==0)return false;///不存在以该结点结尾的字符串。
    ///存在
    p->num=0;
    return true;
}
void init(){root=new node();}
int main()
{
    return 0;
}

eg1 Uva1401–Remember the word

eg2 “strcmp()” Anyone? UVA - 11732

非书本中的eg

1Phone List POJ - 3630

简单判断一个字符串,是否为其他串的前缀。

2The XOR Largest Pair LibreOJ - 10050

求n个数里的最大xor对。(01Trie)

3The xor-longest Path POJ - 3764

题2的升级版(01Trie)

4Nikitosh 和异或 LibreOJ - 10051

题2的升级版(01Trie)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值