[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 ...
随机推荐
- 超详细的Java时间工具类
package com.td.util; import java.sql.Timestamp; import java.text.ParseException; import java.text.Pa ...
- 快速把项目部署到webLogic上
weblogic简介BEA WebLogic是用于开发.集成.部署和管理大型分布式Web应用.网络应用和数据库应 用的Java应用服务器.将Java的动态功能和Java Enterprise标准的安全 ...
- office web app server部署和简单操作
部署环境:windows server 2012 R2,服务器在AD域中 参考网址: https://msdn.microsoft.com/zh-cn/magazine/jj219455(office ...
- Redis-其他命令
1.排序 SORT : SORT sourcekey [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [A ...
- WinMain函数详解(转载再编辑)
在Windows应用程序中,我们可以认为 WinMain() 函数是程序的入口,WinMain()的原型如下: int WINAPI WinMain( HINSTANCE hInstance, HIN ...
- SpringIOC的小例子
IOC IOC--Inversion of Control即控制反转,常常和DI--依赖注入一起被提到. 核心是为了解除程序之间的耦合度. 那么什么样的代码是耦合度高的呢? 假如有个人现在去买苹果 i ...
- AutoMapper在项目中的应用
一.先说说DTO DTO是个什么东东? DTO(Data Transfer Object)就是数据传输对象,说白了就是一个对象,只不过里边全是数据而已. 为什么要用DTO? 1.DTO更注重数据,对领 ...
- Codeforces787D(SummerTrainingDay06-D 线段树+最短路)
D. Legacy time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
- 排序算法(5)--Selection Sorting--选择排序[2]--Heap Sort--堆排序
1.基本思想 具有n个元素的序列 (h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1) (i=1,2,...,n ...
- Vue.js之组件系统
vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. Vue.js组件系统 每一个新技 ...