codeforces#1120C. Compress String(dp+后缀自动机)
题目链接:
https://codeforces.com/contest/1120/problem/C
题意:
从前往后压缩一段字符串
有两种操作:
1.对于单个字符,压缩它花费$a$
2.对于末尾一段字符串,如果这段字符串是已经压缩过字符串的子串,那么可以选择压缩它,花费为$b$
数据范围:
$1\leq |S| \leq 5000$
$1\leq a \leq 5000$
$1\leq b \leq 5000$
分析:
这道题目我们需要解决一个问题,计算某个子串出现的最早位置
转移,如果这个字串出现的最早位置不是当前位置,也就是说这个字串在前面还出现了一次,那么可以执行第二种操作
对于指定状态可以根据子状态转移,取最小的子状态的最早位置
给出子串下标求出子串出现的最早位置,首先得到子串在sam中的状态,根据状态得到最早出现的位置
AC代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5000+10;
char S[maxn];
int n,a,b;
struct suffixautomation
{
int mp[maxn*2][30],fa[maxn*2],ed,ct,len[maxn*2],minpos[maxn*2],deg[maxn*2],pos[maxn][maxn];
int dp[maxn];
suffixautomation(){ed=ct=1;}
inline void ins(int c,int pos)
{
int p=ed;ed=++ct;minpos[ed]=pos;len[ed]=pos;//先初始化size和len
for(;p&&mp[p][c]==0;p=fa[p]){mp[p][c]=ed;}//然后顺着parent树的路径向上找
if(p==0){fa[ed]=1;return;}int q=mp[p][c];//case1
if(len[p]+1==len[q]){fa[ed]=q;return;}//case2
len[++ct]=len[p]+1;//case 3
for(int i=1;i<=26;i++){mp[ct][i]=mp[q][i];}
fa[ct]=fa[q];fa[q]=ct;fa[ed]=ct;
for(int i=p;mp[i][c]==q;i=fa[i]){mp[i][c]=ct;}
}
void solve(){
for(int i=1;i<=n;i++){
int now=1;
for(int j=i;j<=n;j++){
int v=S[j]-'a'+1;
now=mp[now][v];
pos[i][j]=now;
}
}
for(int i=1;i<=ct;i++)deg[fa[i]]++;
queue<int>que;
for(int i=1;i<=ct;i++)if(deg[i]==0)que.push(i);
while(que.size()){
int x=que.front();
int y=fa[x];
que.pop();
minpos[y]=min(minpos[x],minpos[y]);
deg[y]--;
if(deg[y]==0)que.push(y);
}
for(int i=1;i<=n;i++){
dp[i]=dp[i-1]+a;
for(int j=2;j<=i;j++){
if(minpos[pos[j][i]]<j){
dp[i]=min(dp[i],dp[j-1]+b);
break;
}
}
}
printf("%d\n",dp[n]); }
}sam;
int main()
{
scanf("%d %d %d",&n,&a,&b);
scanf("%s",S+1);
for(int i=0;i<maxn*2;i++)sam.minpos[i]=1e9;
for(int i=1;i<=n;i++)sam.ins(S[i]-'a'+1,i);
sam.solve();
return 0;
}
codeforces#1120C. Compress String(dp+后缀自动机)的更多相关文章
- Codeforces 1120C Compress String(DP)
题意:给你一个字符串,有2种消除方式:1:消除一个单独的字母,代价为a.2:s[j]到s[k]是s[1]到s[j - 1]的子串,那么s[j]到s[k]可以消除,代价为b,问最小的代价. 思路:官方题 ...
- 【Hihocoder1413】Rikka with String(后缀自动机)
[Hihocoder1413]Rikka with String(后缀自动机) 题面 Hihocoder 给定一个小写字母串,回答分别把每个位置上的字符替换为'#'后的本质不同的子串数. 题解 首先横 ...
- 【计蒜客】是男人就过 8 题--Pony.AI 题 A. A String Game 后缀自动机+SG函数
[题目]A. A String Game [题意]给定目标串S和n个子串Ti,Alice和Bob轮流选择一个子串操作,必须且只能在子串末尾添加一个字符使得新串也是S的子串,不能操作即输,求胜利者.|S ...
- HDU6583:Typewriter(dp+后缀自动机)
传送门 题意: 给出\(p,q\),现在要你生成一个字符串\(s\). 你可以进行两种操作:一种是花费\(p\)的代价随意在后面添加一个字符,另一种是花费\(q\)的代价可以随意赋值前面的一个子串. ...
- BZOJ 2806: [Ctsc2012]Cheat(单调队列优化dp+后缀自动机)
传送门 解题思路 肯定先要建出来广义后缀自动机.刚开始以为是个二分+贪心,写了一下结果\(20\)分.说一下正解,首先显然\(L_0\)具有单调性,是可以二分的.考虑二分后怎样判合法,对于分割序列很容 ...
- hdu多校第一场 1006 (hdu6583)Typewriter dp/后缀自动机
题意: 有个打字机,在当前字符串后新加一个字花费p,把当前字符串的一个连续子串拷贝到当前字符串的末尾花费q,给定一个字符串,求用打字机打出这个字符串的最小花费. 题解: 容易想到用dp 记dp[i]为 ...
- BZOJ5408: string(广义后缀自动机,LCT)
传送门 解题思路: 首先在后缀树上,确定了一个节点就相当于确定了一个串,那么一个点对应的串在另外一个点对应的串产生贡献,当且仅当这个点在当前点子树内. 那么考虑一个新的点在串中对串答案的贡献在一条树链 ...
- Codeforces 1050D Three Religions (dp+序列自动机)
题意: 给一个1e5的串str,然后有三个起始空串,不超过1000次操作,对三个字符串的一个尾部加一个字符或者减一个字符,保证每个字符不会超过250 每次操作之后询问你这三个串是不是可以组成str的子 ...
- BZOJ.4032.[HEOI2015]最短不公共子串(DP 后缀自动机)
题目链接 1.求A的最短子串,它不是B的子串. 子串是连续的,对B建SAM,枚举起点,在SAM上找到第一个无法匹配点即可.O(n)用SAM能做吗..开始想错了. 2.求A的最短子串,它不是B的子序列. ...
随机推荐
- VS.NET(C#)--2.8_CCS样式
CSS样式 文件命名 StyleSheet.css body { font-size:12px } .button { color:Red; text-decoration:none; ...
- jQuery遍历(2)
上期我们讲了遍历的祖先和后代的问题,现在我们讲讲遍历同胞 同胞拥有相同的父元素. 通过 jQuery,您能够在 DOM 树中遍历元素的同胞元素. jQuery siblings() 方法 siblin ...
- 一种电平转换的方法,使用CPLD
参考应用笔记 http://www.doc88.com/p-0197252336968.html 前言 在原理图设计初期,可能涉及到引脚电平的转换操作,比如主FPGA的某BANK电平为1.5V,但外围 ...
- SAP Marketing Cloud功能简述(二) : Target Group
这个系列的第一篇文章 SAP Marketing Cloud功能简述(一) : Contacts和Profiles,我向大家介绍了SAP Marketing Cloud里的Contacts和Profi ...
- 从SAP社区上的一篇博客开始,聊聊SAP产品命名背后的那份情怀
最近Jerry在SAP社区上看到一篇博客:It's Steampunk now. 博客原文:https://blogs.sap.com/2019/08/20/its-steampunk-now/ 什么 ...
- JAVA笔记整理(六),JAVA中的多态
JAVA引用变量有两个类型:一个是编译时类型,一个运行时类型 编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定.如果编译时类型和运行时类型不一样,就形成了多态. 因为子类其 ...
- 更改Ubuntu下默认Python版本
更改Ubuntu下默认Python版本 首先查看系统内有哪些版本的Python ls /usr/bin/python* 查看当前python版本 python --version 基于用户修改默认版本 ...
- Windows——Thinkpad 开机显示pwmtr64v.dll找不到指定的模块
解决方法:进入设备管理器,展开系统设备分页,找到Lenovo Power Manager ,右键,更新驱动程序,浏览计算机上的驱动程序, 让我从计算机上的可用驱动程序列表中选取,选择Lenovo Po ...
- Java线程(1)
多线程快速入门 线程与进程区别 每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行.也可以把它理解为代码运行的上下文.所以 ...
- eclipse中导入一个web项目
首先 一般会因为环境不同而出错 所以还需要进一步配置,项目上右键properties