[luogu T71973]卡常者π酱
[luogu T71973]卡常者π酱
题意
给定一个长度为 \(n\) 的字符串, 要求将字符串分割为若干段, 每一段要么是一个字符要么是前面几段的并的子串.
如果某一段是一个单独字符, 则产生 \(a\) 的开销.
如果是前几段的并的子串, 则产生 \(b\) 的开销.
如果满足两个条件, 则可以在 \(a,b\) 中任选一个开销.
求划分的最小开销.
\(n\le 5\times 10^6\), 字符集大小 \(\Sigma\le 7\).
题解
冷静分析一下发现是沙雕题
然而题目说不卡常实际上是真的卡常...严格 \(O(n)\) 并不一定能跑过...
我们发现这个沙雕题最后一个串的开销和前面的划分方案无关, 果断想到DP. 设 \(dp_i\) 表示长度为 \(i\) 的前缀的最小划分代价.
然后有个显然的性质, 就是如果有一个后缀满足它在前面出现过, 那么这个后缀的所有后缀同样都满足. 所以不难想到对于当前DP前缀找到满足该性质的最长的后缀, 然后在这个后缀的所有后缀中找最小DP值更新.
不难发现这个过程实际上可以用后缀自动机解决. 对于每个状态都维护一下 \(right\) 集合中的最小值, 也就是当前状态所代表字符串的第一次出现的右端点的位置. 这样我们就可以直接知道当前后缀是否在前面出现过了.
不难发现这个后缀的左端点位置也是单调的, 所以不合法暴力跳就可以 \(O(n)\) 了.
按照刚刚的讨论我们需要把所有合法的后缀的 \(dp\) 值取 \(\min\), 需要单调队列来维护. 但是实际上不难发现 \(dp\) 值是单调不降的, 所以直接取最长合法后缀的左端点处的 \(dp\) 值就可以了.
但是要想A这题还得加点优化. 一个是 \(right\) 集合的最小值的维护, 并不需要给后缀自动机结点基数排序. 因为每次插入的新点的 \(right\) 集合中的值实际上是单调递增的, 而且如果在原来自动机上某个点在另一个点的子树中的话扩展后一定还在那个点的子树里. 所以可以边构造边算.
其次是我们并不需要先构造出整个SAM然后再跑, 我们完全可以边构造边计算最长满足条件的后缀. 因为后面的字符串并不会影响前面已有的信息.
加了这两个优化才卡时限过的...这可真蠢.
(不难分析得到不加两个优化+单调队列实际上也是严格 \(O(n)\) 的时间复杂度)
参考代码
#include <bits/stdc++.h>
const int MAXN=1e7+10;
typedef long long intEx;
int n;
int a;
int b;
int cnt=1;
int last=1;
int root=1;
int s[MAXN];
int buc[MAXN];
int len[MAXN];
int prt[MAXN];
int minr[MAXN];
char str[MAXN];
intEx dp[MAXN];
int chd[MAXN][7];
void Extend(char);
int main(){
scanf("%d%d%d",&n,&a,&b);
scanf("%s",str+1);
int cur=root,curlen=0;
for(int i=1;i<=n;i++){
Extend(str[i]);
int p=str[i]-'a';
while(!chd[cur][p]){
cur=prt[cur];
curlen=len[cur];
}
++curlen;
cur=chd[cur][p];
while(cur!=root&&minr[cur]>i-curlen){
if(i-minr[cur]>len[prt[cur]])
curlen=i-minr[cur];
else{
cur=prt[cur];
curlen=len[cur];
}
}
dp[i]=dp[i-1]+a;
if(curlen)
dp[i]=std::min(dp[i],dp[i-curlen]+b);
}
printf("%lld\n",dp[n]);
return 0;
}
void Extend(char ch){
int x=ch-'a';
int p=last;
int np=++cnt;
last=np;
minr[np]=len[np]=len[p]+1;
while(p&&!chd[p][x])
chd[p][x]=np,p=prt[p];
if(!p)
prt[np]=root;
else{
int q=chd[p][x];
if(len[q]==len[p]+1)
prt[np]=q;
else{
int nq=++cnt;
memcpy(chd[nq],chd[q],sizeof(chd[q]));
len[nq]=len[p]+1;
prt[nq]=prt[q];
prt[q]=nq;
prt[np]=nq;
minr[nq]=minr[q];
while(p&&chd[p][x]==q)
chd[p][x]=nq,p=prt[p];
}
}
}

[luogu T71973]卡常者π酱的更多相关文章
- bzoj3676 [Apio2014]回文串 卡常+SAM+树上倍增
bzoj3676 [Apio2014]回文串 SAM+树上倍增 链接 bzoj luogu 思路 根据manacher可以知道,每次暴力扩展才有可能出现新的回文串. 所以推出本质不同的回文串个数是O( ...
- [luogu1972][bzoj1878][SDOI2009]HH的项链【莫队+玄学卡常】
题目大意 静态区间查询不同数的个数. 分析 好了,成功被这道题目拉低了AC率... 打了莫队T飞掉了,真的是飞掉了QwQ. 蒟蒻想不出主席树的做法,就换成了莫队... 很多人都不知道莫队是什么... ...
- BZOJ3286 Fibonacci矩阵 矩阵 快速幂 卡常
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3286 题意概括 n,m,a,b,c,d,e,f<=10^1000000 题解 神奇的卡常题目 ...
- 【xsy1120】 支援(assist) dp+卡常
妙啊算错时间复杂度了 题目大意:给你一棵$n$个节点的二叉树,每个节点要么是叶子节点,要么拥有恰好两个儿子. 令$m$为叶子节点个数,你需要在这棵二叉树中选择$i$个叶子节点染色,叶节点染色需要一定的 ...
- BZOJ1878 [SDOI2009] HH的项链 [莫队,卡常]
BZOJ传送门,洛谷传送门 HH的项链 Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义. ...
- 【卡常 bitset 分块】loj#6499. 「雅礼集训 2018 Day2」颜色
好不容易算着块大小,裸的分块才能过随机极限数据:然而这题在线的数据都竟然是构造的…… 题目描述 有 $n$ 个数字,第 $i$ 个数字为 $a_i$. 有 $m$ 次询问,每次给出 $k_i$ 个区间 ...
- BZOJ 3595: [Scoi2014]方伯伯的Oj Splay + 动态裂点 + 卡常
Description 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题. Oj上注册了n个用户,编号为1-”,一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和 ...
- [SPOJ] DIVCNT2 - Counting Divisors (square) (平方的约数个数前缀和 容斥 卡常)
题目 vjudge URL:Counting Divisors (square) Let σ0(n)\sigma_0(n)σ0(n) be the number of positive diviso ...
- CH5102/SPOJ?? Mobile Service/P4046 [JSOI2010]快递服务[线性dp+卡常]
http://contest-hunter.org:83/contest/0x50%E3%80%8C%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E3%80%8D%E4%B ...
随机推荐
- 小程序获取地址授权的修改 wx.openSetting需点击
开发者可以通过 wx.openSetting 接口来打开小程序设置界面并返回用户的设置结果.在原来的 wx.openSetting 接口中,我们允许开发者直接调用此接口,但目前我们发现有不少开发者滥用 ...
- PBN飞越转弯Flyover衔接TF、CF航段保护区组图
PBN飞越转弯Flyover衔接TF.CF航段虽不常用,但也很重要,与旁切转弯有一定的相似性. 飞越转弯 flyover-TF/CF 叠加图: 飞越转弯 flyover-TF/CF 分解图:
- zoj Beautiful Number(打表)
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2829 题目描述: Mike is very lucky, as ...
- 最好用的mongodb可视化工具
TreeSoft数据库管理系统,采用web方式,对mongoDB进行管理维护,一次布署,到处使用, 功能包括:mongoDB数据的查看,新增,编辑,删除,shell命令的执行,树状展示,数据导出JSO ...
- Java - 线程让步和休眠
Java多线程系列--“基础篇”06之 线程让步 概要 本章,会对Thread中的线程让步方法yield()进行介绍.涉及到的内容包括:1. yield()介绍2. yield()示例3. yield ...
- 4.Factory Pattern(工厂模式)
工厂模式(Factory Pattern)定义: 定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到子类. 针对实现编程,但是当我们每次使用new时候,不正是在针对 ...
- HDU4280(KB11-G 最大流)
Island Transport Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- HDU1007(最近点对)
Quoit Design Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- iframe 页面刷新
1.点击刷新 [1].html页面代码 <a href="javascript:;" title="刷新当前页" id="Refresh&quo ...
- SSM(Spring MVC +Spring+Mybatis)整合——maven工程
所谓的SSM 其实就是Spring MVC下整合mybatis. 具体的定义网络上都有,很详细. 这里只说项目的搭建步骤. 第一步 新建maven工程 工程目录如下: 配置pom.xml文件,引入所需 ...