算法题目二:寻找最长重复子序列(1) trie树

Trie 与 AC自动机 Trie树(字典树)与AC自动机。 阅读详情

本文是转载。原作者的声明如下:

 

作者:海子  
本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
本文只是作为个人平时学习的记录,不做任何用途。

Trie树

       Trie树也称字典树,因为其效率很高,所以在在字符串查找、前缀匹配等中应用很广泛,其高效率是以空间为代价的。

一.Trie树的原理

    利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低查询操作的复杂度。

    下面以英文单词构建的字典树为例,这棵Trie树中每个结点包括26个孩子结点,因为总共有26个英文字母(假设单词都是小写字母组成)。

    则可声明包含Trie树的结点信息的结构体:

#define MAX 26

typedef struct TrieNode               //Trie结点声明 
{
    bool isStr;                      //标记该结点处是否构成单词 
    struct TrieNode *next[MAX];      //儿子分支 
}Trie;

其中next是一个指针数组,存放着指向各个孩子结点的指针。

    如给出字符串"abc","ab","bd","dda",根据该字符串序列构建一棵Trie树。则构建的树如下:


Trie树的根结点不包含任何信息,第一个字符串为"abc",第一个字母为'a',因此根结点中数组next下标为'a'-97的值不为NULL,其他同理,构建的Trie树如图所示,红色结点表示在该处可以构成一个单词。很显然,如果要查找单词"abc"是否存在,查找长度则为O(len),len为要查找的字符串的长度。而若采用一般的逐个匹配查找,则查找长度为O(len*n),n为字符串的个数。显然基于Trie树的查找效率要高很多。

但是却是以空间为代价的,比如图中每个结点所占的空间都为(26*4+1)Byte=105Byte,那么这棵Trie树所占的空间则为105*8Byte=840Byte,而普通的逐个查找所占空间只需(3+2+2+3)Byte=10Byte。

二.Trie树的操作

    在Trie树中主要有3个操作,插入、查找和删除。一般情况下Trie树中很少存在删除单独某个结点的情况,因此只考虑删除整棵树。

1.插入

  假设存在字符串str,Trie树的根结点为root。i=0,p=root。

  1)取str[i],判断p->next[str[i]-97]是否为空,若为空,则建立结点temp,并将p->next[str[i]-97]指向temp,然后p指向temp;

   若不为空,则p=p->next[str[i]-97];

  2)i++,继续取str[i],循环1)中的操作,直到遇到结束符'\0',此时将当前结点p中的isStr置为true。

2.查找

  假设要查找的字符串为str,Trie树的根结点为root,i=0,p=root

  1)取str[i],判断判断p->next[str[i]-97]是否为空,若为空,则返回false;若不为空,则p=p->next[str[i]-97],继续取字符。

  2)重复1)中的操作直到遇到结束符'\0',若当前结点p不为空并且isStr为true,则返回true,否则返回false。

3.删除

  删除可以以递归的形式进行删除。

测试程序:

/*Trie树(字典树) 2011.10.10*/
 
#include <iostream>
#include<cstdlib>
#define MAX 26
using namespace std;
 
typedef struct TrieNode                     //Trie结点声明 
{
    bool isStr;                            //标记该结点处是否构成单词 
    struct TrieNode *next[MAX];            //儿子分支 
}Trie;
 
void insert(Trie *root,const char *s)     //将单词s插入到字典树中 
{
    if(root==NULL||*s=='\0')
        return;
    int i;
    Trie *p=root;
    while(*s!='\0')
    {
        if(p->next[*s-'a']==NULL)        //如果不存在,则建立结点 
        {
            Trie *temp=(Trie *)malloc(sizeof(Trie));
            for(i=0;i<MAX;i++)
            {
                temp->next[i]=NULL;
            }
            temp->isStr=false;
            p->next[*s-'a']=temp;
            p=p->next[*s-'a'];   
        }   
        else
        {
            p=p->next[*s-'a'];
        }
        s++;
    }
    p->isStr=true;                       //单词结束的地方标记此处可以构成一个单词 
}
 
int search(Trie *root,const char *s)  //查找某个单词是否已经存在 
{
    Trie *p=root;
    while(p!=NULL&&*s!='\0')
    {
        p=p->next[*s-'a'];
        s++;
    }
    return (p!=NULL&&p->isStr==true);      //在单词结束处的标记为true时,单词才存在 
}
 
void del(Trie *root)                      //释放整个字典树占的堆区空间 
{
    int i;
    for(i=0;i<MAX;i++)
    {
        if(root->next[i]!=NULL)
        {
            del(root->next[i]);
        }
    }
    free(root);
}
 
int main(int argc, char *argv[])
{
    int i;
    int n,m;                              //n为建立Trie树输入的单词数,m为要查找的单词数 
    char s[100];
    Trie *root= (Trie *)malloc(sizeof(Trie));
    for(i=0;i<MAX;i++)
    {
        root->next[i]=NULL;
    }
    root->isStr=false;
    scanf("%d",&n);
    getchar();
    for(i=0;i<n;i++)                 //先建立字典树 
    {
        scanf("%s",s);
        insert(root,s);
    }
    while(scanf("%d",&m)!=EOF)
    {
        for(i=0;i<m;i++)                 //查找 
        {
            scanf("%s",s);
            if(search(root,s)==1)
                printf("YES\n");
            else
                printf("NO\n");
        }
        printf("\n");   
    }
    del(root);                         //释放空间很重要 
    return 0;
}

经运行可以正确运行,若加上提示输入的语句输出会更好。
AC自动机(trie图版) AC自动机是一个多模字符串匹配的自动机(网上说的),主要作用是在一个长串中同时进行多个字符串的匹配 基础芝士: trie树(字典树) 烤馍片kmp单模字符串匹配 如果不会的建议去网上学一下(本篇讲解略过) 这里重点讲一讲AC自动机 (由于本蒟蒻不会指针,所以所有算法一律不使用指针,请神犇们谅解) 例:luogu3796 AC自动机(加强版) 其实AC自动机就是在trie树上构造KM... 阅读详情

相关推荐

动态规划之最长递增子序列 最长不重复子串 最长公共子序列

【前言】动态规划:与分治法相似,即通过组合子问题来求解原问题,不同的是分治法是将问题划分为互不相交的子问题,递归求解子问题,再将他们组合起来求出原问题的解。 动态规划则应用于子问题重叠的情况,通常用来求解最优化问题。这类问题可以有很多可行解,每个解都有一个值,我们希望寻找最优值的解。 通常有4个步骤来设计动态规划算法: 1.刻画一个最优解的结构特征。 2.递归地定义最优解的值。 3.计算

虐汪狂人巴甫洛夫的博客 4355

Trie树

Trie树 Trie树也称字典树,因为其效率很高,所以在在字符串查找、前缀匹配等中应用很广泛,其高效率是以空间为代价的。 一.Trie树的原理 利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低查询操作的复杂度。 下面...

weixin_30753873的博客 283

JAVA算法:最长重复子序列(JAVA)

JAVA算法:最长重复子序列(JAVA) Longest Repeating Subsequence Given a string, find length of the longest repeating subseequence such that the two subsequence don’t have same string character at same position, i...

梅森上校的博客 业精于勤荒于嬉,形成于思毁于随。 1322

AC自动机(Trie 板子)&后缀数组模板(解决原串与子串问题)

大自然的帮运工 使用板子注意事项: 注意: 1.串是否全是小写字母 2.根节点为1 3.节点数不超过maxn 4.多组数据注意 清空 5.复杂度嘛。。。。。建树o(n*len) 前置知识:Trie树 需求: 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。 输入n个模式串, 一个原串 输出结果: 原串中含有模式串的个数。 in: 6 abcd cd cd cdac aab abcdac out: 5 #include<bits/stdc++.h> #define maxn

weixin_45819197的博客 411

利用VS2019编写安卓APP的步骤和所遇问题的解决办法

遇到了代码错误,这个可以将鼠标箭头置于错误代码处,这样VS2019给你解决办法,给的方法不能解决,并且读了程序都没有问题,那么你应该重启软件,这样还是不能解决,你尝试重新生成解决方案,还是不能解决有可能是运用的代码与当前版本不相符和、过时了,这个时候应当运用相应版本的代码。注:VS2019编写APP的空间不是很稳定,当你写的代码没有问题,但是出现了报错,可能是空间崩溃了,这个时候可以重启软件。点击“+”号,创建密钥存储,输入“别名”、“密码”、以及下面中的任意一项,直至红色框消失后。

youbestcando的博客 7813

TCP Reno/CUBIC 拥塞控制算法对比:从 Tahoe 到 BBR 的 4 种核心策略演进

本文深入解析了TCP拥塞控制算法的演进历程,从经典的Tahoe、Reno到现代的CUBIC和BBR,详细对比了4种核心策略的实现机制与性能差异。通过分析拥塞窗口、流量控制等关键技术,揭示了不同算法在高带宽延迟网络中的优化方向,为网络协议栈优化提供理论依据和实践指导。

weixin_33725239的博客 440

Trie树与AC算法

作者:myjoying         时间:2012年9月10日                在我的前一篇博文《AC算法--多模式匹配(论文解析版)》(http://blog.youkuaiyun.com/myjoying/article/details/7960534)中介绍了AC算法的实现原理,但是并没有给出AC算法的具体实现。AC算法的实现必须首先解决几个问题。首先需要解决的是goto表的实现

myjoying的专栏 5475

【BigWorld 游戏服务器引擎】Cell 架构设计介绍,及Java实现方案的探索

横向扩展(Scalability):通过动态增减CellApp和BaseApp的数量,可以轻松应对玩家人数的变化。世界可以做得非常大,只需增加更多的 Cell。负载分离(Load Separation):将不同性质的负载分离,避免了单一进程瓶颈。CPU 密集型的实时计算(CellApp)和 I/O 密集型的数据操作(BaseApp)互不影响。高效的视野管理(AOI):每个 Cell 只关心自己区域内和边界上的实体,大大降低了计算复杂度。容错性:某个CellApp。

代码时光 1205

算法题目二:寻找最长重复子序列(3) 后缀树

本文为转载,有所修改。原作者文章为:http://hi.baidu.com/zealot886/item/5d35b442d059701a886d1072(百度空间) 仅为个人学习备份之用途,无任何其他用途!   写这篇文章,主要是因为最近有个课题设计,里面用的字符串匹配。 学习后缀树之前,先了解一下Trie这个数据结构 Trie是一种搜索树,可用于存储并查找字符串。

1ouis的专栏 1978

Android 14 (AOSP) 源码架构深度解析与开发者指南

Android14源码的仓库指南信息

保持专注,保持热爱 1186

【系统架构设计师】2026年上半年真题论文:论高并发系统的设计与实践

本文围绕高并发系统架构设计展开,重点论述了电商秒杀系统的实战经验。文章采用"痛点-解决方案-效果"的逻辑结构,从缓存设计、异步处理、限流降级、数据库优化等6个维度详细阐述了应对高并发的技术策略。其中,重点介绍了多级缓存体系、基于消息队列的异步处理机制和微服务拆分实践,并辅以实际案例说明如何解决超卖、缓存雪崩等典型问题。全文强调高并发设计需要系统性思维,通过空间换时间、异步换吞吐、横向换能力等原则,最终实现系统吞吐量从500TPS提升至20000TPS的性能突破。

数据知道的博客 1157

算法题目二:寻找最长重复子序列(2) trie树与后缀树的应用

本文是转载!原博客地址为:http://www.cnblogs.com/aiyelinglong/archive/2012/04/09/2439777.html 仅作为个人算法学习的记录之用,不用做任何其他用途。   Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于

1ouis的专栏 1278

WorkBuddy 连接百度网盘:能查能上传,但别指望 AI 帮你下载

本文介绍了如何通过WorkBuddy连接百度网盘实现文件管理功能。首先需要在百度开放平台创建应用并获取AppKey等凭证,然后通过拼接授权URL获取Access Token并填入WorkBuddy。实际测试表明,该连接器支持查看目录结构、搜索文件及上传文档,但无法实现文件下载和创建分享链接,原因是百度网盘MCP Server未提供相关接口。使用前需明确功能限制,该方案适合需要远程查阅网盘内容但不涉及下载的场景。

u011186532的专栏 1924

最长连续不重复子序列python题解-双指针

看了很久,发现这道题目应该是有些前提的,以至于我开始一直往错的方向去想,将题目大大复杂化了

Not_Big_Mouth的博客 1911

H3C交换机命令大全,分模块好记忆!

在深入命令之前,我们先来了解H3C交换机的命令行基础。<H3C>[H3C]常用基础命令如下:这些基础命令是操作H3C交换机的敲门砖,熟练掌握后,我们将按模块深入探讨更具体的配置命令。H3C交换机的命令可以按功能模块分类,包括系统管理、接口配置、VLAN操作、链路聚合、路由配置、安全管理等。

网络技术联盟站 782

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

基础算法-最长连续不重复子序列

最长连续不重复子序列 method //朴素做法 for (int i = 0; i < n; i ++) for (int j = 0; j <= i; j ++) if (check(j, i)) { res = max(res, i - j + 1); } //双指针做法 for (i...

ai_XZP_master 2480

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

最长不重复子序列_最长重复子序列

最长不重复子序列Description: 描述: This question has been featured in interview rounds of Amazon. 这个问题已在亚马逊的采访回合中提到。 Problem statement: 问题陈述: Given string str, find the length of the longest repeating sub...

cumtv80668的专栏 991

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

代码随想录算法训练营Day52|300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

在结束代码随想录中的股票问题后,又是一个新的专题,本题是子序列问题的第一题,子序列问题是动态规划解决的经典问题。本题相较于上一题,最大的区别在于“连续”,对于连续问题的处理必须要重点考虑相邻元素。本题与前面几题又不一样了,本题比较的是两个数组拥有的最长重复的子数组,因此不能仅仅再只针对一个数组,dp数组也要变成二维;子序列问题第一天结束!

m0_68682181的博客 1332

最长递增子序列 最长连续递增序列 最长重复子数组

为什么一定表示 “以nums[i]结尾的最长递增子序” ,因为我们在 做 递增比较的时候,如果比较 nums[j] 和 nums[i] 的大小,那么两个递增子序列一定分别以nums[j]为结尾 和 nums[i]为结尾, 要不然这个比较就没有意义了,不是尾部元素的比较那么 如何算递增呢。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;

波风水门的博客 1199

【基础算法】双指针---最长连续不重复子序列

今天我们来继续学习双指针的算法例题,【最长连续不重复子序列】,码字不易,请多多支持。

云小逸的博客 1453

300.最长递增子序列 674.最长连续递增序列 718.最长重复子数组

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

qq_43361824的博客 1738

最长重复子序列问题的后缀数组解法

最长重复子序列问题除了使用穷举法,还可以使用后缀数组和后缀树来求解。这里给出使用后缀数组解决的最长重复子序列的过程,并以“banana”为例进行演示。首先写下一个比较两个字符串从头开始共同部分的长度的函数: int comlen(char *p, char *q) { int i = 0; while(*p&&(*p++ == *q++)) i++; re

ryan_jianjian的博客 1273

24暑假算法刷题 | Day42 | 动态规划 X | 子序列问题 I | LeetCode 300. 最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组

day42:动态规划X,子序列问题I

weixin_54468359的博客 1651

算法训练(leetcode)二刷第三十七天 | *300. 最长递增子序列、674. 最长连续递增序列、*718. 最长重复子数组

LeetCode二刷

weixin_43872997的博客 889

算法学习——LeetCode力扣动态规划篇8(300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组、1143. 最长公共子序列)

算法学习——LeetCode力扣动态规划篇8(300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组、1143. 最长公共子序列)

拉依达不拉跨的博客 1070
上一篇: 算法题目一:全排列(C++实现)
下一篇: 算法题目二:寻找最长重复子序列(2) trie树与后缀树的应用
louis9212
博客等级 码龄14年 8粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值