热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[HDU4787]GREWordsRevenge解题报告

这是我之前博客里提到的一道AC自动机的练手题,但是要完成这道题,我之前博客里提到的东西还不够,这里总结一下这道题。这道题不是一般的裸的AC

  这是我之前博客里提到的一道AC自动机的练手题,但是要完成这道题,我之前博客里提到的东西还不够,这里总结一下这道题。

  这道题不是一般的裸的AC自动机,它的询问和插入是交叉出现的所以用我之前写的板子不大合适,这道题在构建自动机时不能改变原有的 Trie树 的结构,所以没有代表字符串的结点的不需要去改它的值,所以我在 build() 函数 处做了一些修改。在复杂度方面,如果是强上普通的AC自动机,最差会达到O(n^2),感觉不太好。我们这里可以用到平方分割的套路,搞大小两个自动机,每次插入都在小自动机上进行,当小自动机里的结点达到一定量(sqrt(n))时,就将两自动机合并,并将小自动机清空。合并的方式也很好理解,就将两个自动机的节点一一对应,若小自动机上的结点在大自动机上没有,就在大自动机上新建结点,并修改它的值。总复杂度大概是这样:O(n*sqrt(n)(小的)+O(sqrt(n)*n)(大的)=O(n*sqrt(n))。其实那个上界也不一定要严格的根号n,自己大概估计一个常数就差不多了。哦对,还有一点,我发现好多板子里在构建新结点时都打了一个 newnode() 函数,包括我自己的板子也是这么打的。这样打其实是很慢的,我在做这道题时就各种 T飞 ,后来把这个去掉搞成其他的方法就快了很多(虽然我也不知道为什么),下面的代码里会体现。

  祝大家切题愉快

#include
#include
#include
#include
#include
#include
#define maxn (511111)
#define N (6000000)
#define il inline
#define ll long long
#define RG register
using namespace std;
char s[N],ss[N];struct Trie{int son[maxn][2],fail[maxn],size,root;bool val[maxn]; //标记是否出现il void init(){size&#61;1; root&#61;0;memset(son,0,sizeof(son));memset(val,0,sizeof(val));memset(fail,0,sizeof(fail));}il int idx(char c){ //卡常专用return c-&#39;0&#39;;}il int insert(char *s){ //插入新单词RG int cur&#61;root;for(RG int i&#61;0;s[i];i&#43;&#43;){ //卡常小技巧&#xff0c;不要每次计算lenRG int id&#61;idx(s[i]);if( !son[cur][id] ) son[cur][id]&#61;size&#43;&#43;;cur&#61;son[cur][id];}val[cur]&#61;true;return cur;}il bool in(char *s){ //查询单词是否在自动机内RG int cur&#61;root;for(RG int i&#61;0;s[i];i&#43;&#43;){RG int id&#61;idx(s[i]);if( !son[cur][id] ) return false;cur&#61;son[cur][id];}return val[cur];}il void build(){ //构建自动机queueQ;for(RG int i&#61;0;i<2;i&#43;&#43;)if( son[root][i] ) //只加入队列&#xff0c;不用修改值Q.push(son[root][i]);while(!Q.empty()){RG int cur&#61;Q.front(); Q.pop();for(RG int i&#61;0;i<2;i&#43;&#43;){RG int Son&#61;son[cur][i];if(!Son) continue;Q.push(Son); //同上RG int f&#61;fail[cur];while(f && !son[f][i] ) f&#61;fail[f];fail[Son]&#61;son[f][i];}}}il int query(char *s){ //查询次数RG int cur&#61;root,ans&#61;0;for(RG int i&#61;0;s[i];i&#43;&#43;){RG int id&#61;idx(s[i]);while(cur && !son[cur][id] ) cur&#61;fail[cur];cur&#61;son[cur][id];RG int k&#61;cur;while(k){ans&#43;&#61;val[k];k&#61;fail[k];}}return ans;}
}small,big;il void dfs(RG int u,RG int v){ //用于合并for(RG int i&#61;0;i<2;i&#43;&#43;)if(small.son[v][i]){RG int cur2&#61;small.son[v][i];if( !big.son[u][i] ){memset(big.son[big.size],0,sizeof(big.son[big.size]));big.son[u][i]&#61;big.size&#43;&#43;; //建立新结点}RG int cur1&#61;big.son[u][i];big.val[cur1] |&#61;small.val[cur2];dfs(cur1,cur2);}
}il void join(){dfs(0,0);small.init();big.build();
}int main(){RG int Case,n;scanf("%d",&Case);for(RG int k&#61;1;k<&#61;Case;k&#43;&#43;){printf("Case #%d:\n",k);scanf("%d",&n);small.init(); big.init();RG int l&#61;0;while(n--){scanf("%s",s);RG int len&#61;strlen(s&#43;1);ss[0]&#61;s[0];for(RG int i&#61;0;i2333 ) join();}else{l&#61;small.query(ss&#43;1)&#43;big.query(ss&#43;1);printf("%d\n",l);}}}return 0;
}

  真是服了这鬼畜的缩进。。。真难看。。。

转:https://www.cnblogs.com/Hero-of-someone/p/7157408.html



推荐阅读
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • JUC(三):深入解析AQS
    本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 双指针法在链表问题中应用广泛,能够高效解决多种经典问题,如合并两个有序链表、合并多个有序链表、查找倒数第k个节点等。本文将详细介绍这些应用场景及其解决方案。 ... [详细]
  • 利用python爬取豆瓣电影Top250的相关信息,包括电影详情链接,图片链接,影片中文名,影片外国名,评分,评价数,概况,导演,主演,年份,地区,类别这12项内容,然后将爬取的信息写入Exce ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 最详尽的4K技术科普
    什么是4K?4K是一个分辨率的范畴,即40962160的像素分辨率,一般用于专业设备居多,目前家庭用的设备,如 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 文章目录Golang定时器Timer和Tickertime.Timertime.NewTimer()实例time.AfterFunctime.Tickertime.NewTicke ... [详细]
  • 本文提出了一种基于栈结构的高效四则运算表达式求值方法。该方法能够处理包含加、减、乘、除运算符以及十进制整数和小括号的算术表达式。通过定义和实现栈的基本操作,如入栈、出栈和判空等,算法能够准确地解析并计算输入的表达式,最终输出其计算结果。此方法不仅提高了计算效率,还增强了对复杂表达式的处理能力。 ... [详细]
  • 题目解析给定 n 个人和 n 种书籍,每个人都有一个包含自己喜好的书籍列表。目标是计算出满足以下条件的分配方案数量:1. 每个人都必须获得他们喜欢的书籍;2. 每本书只能分配给一个人。通过使用深度优先搜索算法,可以系统地探索所有可能的分配组合,确保每个分配方案都符合上述条件。该方法能够有效地处理这类组合优化问题,找到所有可行的解。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
author-avatar
手机用户2502917001
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有