2017.8.20 后缀自动机(p3804) 思考记录
首先构造sam还是比较巧的
首先它的总点数和边数不会超过2*n,而且每个节点下面相同的字母节点只有一个
所以它实质上是把一个字母用了多次
sam是每次加入一个节点,然后合理的安排位置、边、辅助点使之更优
1、父指针:指向同样能接受下一个字符的节点:
设根节点(起点)为s
如 aca ,这时第二个a的父指针就指向第一个a,这样下一个节点x就会和这两个a连边,使s-a-c-a-x 和s-a-x 同时存在
如果不用父指针,都从s出发,那s后面就有两个字符为a的节点,显然不优(匹配a时不知道走哪个,就不是自动机了)
所以这第一个a就有两个意义了
父指针使自动机区别于暴力加后缀();
还有添加辅助节点,,如abacc 第二个c会找到第一个c来尝试优化,,但起点后面只能有一个c,并且这个c还肩负着后缀c、cc 那怎么办?
新建一个节点c,复制第一个c和根、子节点的关系,使它具有和第一个c相同的功能,于是,cc串就出现了
它还需要作为后缀c,,所以本身可以接受节点,第一个c和第二个c的父指针都指向它,这样它就相当于有两个意义
这个题要求的使子串长度*出现次数的最大值,,出现次数好说,因为父指针都是指向前面的相同字符的节点,所以倒序递推即可在第一次出现该字符时统计出字符出现次数
还剩一个长度,,l数组就有用了,它记录的是从根节点出发的最长子串、所以计数排序之后,如果它的节点的出现次数为n,那它前面的节点的出现次数也一定是>=n的(因为爬相同的节点需要一个一个爬,不可能跳步),所以size*l取最值即可
码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define N 1000006
int cnt,last;
int ch[N<<1][28],fu[N<<1];
ll sz[N<<1],l[N<<1],ans,c[N<<1],a[N<<1];
char str[N];
void jia(int o)
{int np=++cnt,p=last;last=np;l[np]=l[p]+1;for(;p&&ch[p][o]==0;p=fu[p])ch[p][o]=np;if(!p)fu[np]=1;else{int q=ch[p][o];if(l[p]+1==l[q])fu[np]=q;else{int i,nq=++cnt;l[nq]=l[p]+1;for(i=0;i<=26;i++)ch[nq][i]=ch[q][i];fu[nq]=fu[q];fu[q]=fu[np]=nq;for(;ch[p][o]==q;p=fu[p])ch[p][o]=nq; } }sz[np]=1;
}
int main()
{scanf("%s",str);cnt=1;last=1;int i,n=strlen(str);for(i=0;i<n;i++)jia(str[i]-'a');for(i=1;i<=cnt;i++)c[l[i]]++;for(i=1;i<=cnt;i++)c[i]+=c[i-1];for(i=1;i<=cnt;i++)a[c[l[i]]--]=i;//for(int i=1;i<=cnt;i++)cout<<a[i]<<" "<<l[a[i]]<<endl;for(i=cnt;i>=1;i--){int p=a[i];sz[fu[p]]+=sz[p];if(sz[p]>1)ans=max(ans,sz[p]*l[p]); }printf("%lld",ans);
}
2017.8.20 后缀自动机(p3804) 思考记录相关推荐
- 2017.9.20 回文串 思考记录
这个题官方解法是 manacher+sa. 但pam诞生之后这个题就变成了模板题.. 事实证明,科技是第一解题力 网上的pam讲解感觉很迷啊,,核心思想一张图就搞定了: 黑色箭头就是指向以右端点为结尾 ...
- 2017.4.20 hanoi双塔问题 思考记录
题目中也提示了有递推关系.. 其实答案就是(2^n-1)*2 用高精循环算出来即可 码: #include<iostream> #include<cstdio> using n ...
- 后缀自动机 ---- P3804 【模板】后缀自动机(求每个等价类最长串的出现次数)
后缀自动机一些关键点 首先后缀自动机上面每个节点都是一个等价类并且是最长的字符串的结尾 后缀自动机上的fail链反建就是parent tree,下面是SAM和Parent tree的构造 对于这道模板 ...
- 2017.3.27 生成魔咒 思考记录(有史以来最不容易)
做了三天,实在太坑了 终于100文章了 这个题要求每次在单词的末尾加一个字母,再查询本质不同的串的个数.. 既然是子串满足连续性,那就可以后缀数组+lcp搞了: 具体计算方式: 由于后缀数组的开头是包 ...
- 2017.3.25 魔术球问题 思考记录
这个题还是不难的..(想了20分钟就出完解) 二分+网络流检验,,能加在上面的数大的向小的连边 总点数-最大匹配>n :{l=mid+1, 记录答案 } else ...
- 2017.10.5 最短母串 思考记录
这个题n<=15,可以用10表示选取情况下的最优值 预处理两个串之间的连接关系,然后枚举状态转移 然而这个题还要输出方案,,而且还不让你开空间. 所以只能记录前继动态判断.. 所以十分难写难调 ...
- 2017.9.28 CF #R2 B 思考记录
题目大意: 给一个n*n的图,每个点有点权,求从左上角走到右下角,把一路的点权乘起来,求后缀零个数最小值,并输出方案 首先0是特例,因为走了他,后缀零个数一定是1 然后如果有数字相乘得到0,那相当于* ...
- 2017.9.26 块的计数 思考记录
这种题就属于那种描述很简单,要求很简单,但就是无从下手的题 这个题我只有n根n做法..枚举因数检验.. 首先对于任何块的大小,方案唯一,这是显然的,,如果划分位置改变1,一定有一个位置+1,一个位置- ...
- 2017.8.8 魔兽地图DotR 思考记录
假题害人.. 明明说了是一棵树,却还要强行加一组坑爹数据 所以网上的题解挂了好多 这题是很综合的树上背包问题. 由依赖关系转化为一些枚举来跑多重背包 由于是 "一棵树" 所以 ...
最新文章
- Python创建二维数组(关于list的一个小坑)
- 央行放水点燃房价,普通家庭如何理财?
- micopython 18b20_micropython typboaed v202连接DS18B20测温小实验
- mina mysql_Mina学习笔记(二)
- Flink 必知必会经典课程四:Fault-tolerance in Flink
- 树莓派4B (aarch64) 安装PyTorch 1.8 的可行方案
- android像素鸟,像素鸟Flappy Bird
- 知识图谱运用于推荐系统
- 为什么我写了一万小时的代码,却仍然成不了架构师?
- 如何确定恶意软件是否在自己的电脑中执行过?
- 编程语言中的常量折叠(const folding)
- 企业微信发送消息php,PHP实现微信模板消息发送给指定用户
- javafx 二维图形编程及可视化操作
- win10-用户忘记密码如何登录
- 【渝粤教育】电大中专中药调剂作业 题库
- lca rmq 算法资料
- ROS通信机制~话题通信(PublisherSubscriber)·笔记2
- 【GEE笔记5】数据筛选Filter
- Java double 保留一个小数、理解BigDecimal、Java解决精度问题
- blender 绘制离散顶点, SMPL骨架绘制
热门文章
- 关于Python生成器的一个小问题(StopIteration)
- Neo4j fails creating index,创建索引失败
- 零基础机器学习(1)- 我们为什么要学习Python?
- CSS练习_无限滚动
- php限制注册频率,php如何限制某个ip提交的次数
- html盒子中盒子排列,css3中弹性盒排布使用方法
- mysql以下日期函数正确的_[数据库]MYSQL基础03(日期函数)
- 设置go path_Go命令的PATH安全性
- 骑士聚会问题(PPT截取)
- zsh 使用通配符功能