P9523 [JOIST 2022] 复制粘贴 3 / Copy and Paste 3 分析
题目概述
在这个编辑器中,可以执行如下几种操作来输入某个字符串,设 \(X\) 为屏幕上的字符串,\(Y\) 为剪切板中的字符串,初始均为空串:
- 操作 A:输入字符 \(c\),即将 \(X\) 更新为 \(X+c\)。
- 操作 B:选择所有字符并剪切,即将 \(Y\) 更新为 \(X\),并将 \(X\) 置为空串。
- 操作 C:将剪切板中的字符串粘贴到当前字符串末尾,即将 \(X\) 更新为 \(X+Y\)。
对于字符串或字符 \(x,y\),\(x+y\) 表示将 \(x\) 和 \(y\) 顺次拼接得到的结果。使用一次操作 A,B,C 分别要花费 \(A,B,C\) 单位时间。
你安装了“没啥用编辑器”,并想要尽可能快地输入一个长度为 \(N\) 的字符串 \(S\)。
你需要计算出最少需要花费多少时间。
对于所有数据,满足:\(1\leq N\leq 2500\)。
分析
好题!
首先考虑到有先后顺序问题,直接考虑区间 \(dp\)。
设 \(f_{i,j}\) 表示得到 \([i,j]\) 的最小代价。
显然的,有加字符的代价进行转移。
当然还需要考虑怎么转移粘贴的情况。
考虑 \([i,j]\rightarrow[p,j]\) 进行转移(\(p<i\),肯定考虑最大的 \(p\),更优)。
考虑枚举一下 \([p,j]\) 出现 \([i,j]\) 的次数。
然后进行转移即可,转移很简单。
这里的时间复杂度是 \(\mathcal{O}(n^2\log n)\) 的,非常优秀(假设 \(\mathcal{O}(1)\) 得到 \(p\))。
考虑怎么快速找到 \(p\),这也是本题一大难点。
大概来说是这样的,这个过程十分巧妙。
我们考虑从左端点为 \(i\) 的怎么扩展到左端点为 \(j\) 的。
首先我们需要知道长度,其次我们需要这个长度下的最大的上一个。
后面哪个不妨设 \(pre_{i,j}\) 表示以 \(i\) 为左端点与他前 \(j\) 个子串相等的最大的上一个。
依据这个设 \(lcp_{i,j}\) 表示以 \(i\) 为左端点和以 \(j\) 为左端的他们的最长前缀(不重叠)。
这个是好维护的,可以 \(\mathcal{O}(n^2)\) 解决,而且我们不难发现他其实是不一定连续的,满足我们的需求。
代码
时间复杂度 \(\mathcal{O}(n^2\log n)\)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define int long long
#define N 2505
using namespace std;
int lcp[N][N],pre[N][N],f[N][N];
int A,B,C,n;
char s[N];
signed main(){
cin >> n;
scanf("%s",s + 1);
cin >> A >> B >> C;
for (int i = n;i;i --) {
for (int j = i - 1;j;j --) {
lcp[i][j] = (s[i] == s[j] ? lcp[i + 1][j + 1] + 1 : 0);
lcp[i][j] = min(lcp[i][j],i - j);
if (!pre[i][lcp[i][j]]) pre[i][lcp[i][j]] = j;
}
for (int j = n;j;j --) pre[i][j] = max(pre[i][j],pre[i][j + 1]);
}
memset(f,0x3f,sizeof f);
for (int i = 1;i <= n;i ++) f[i][i] = A;
for (int len = 1;len <= n;len ++)
for (int i = 1;i + len - 1 <= n;i ++) {
int j = i + len - 1;
f[i][j] = min(min(f[i][j],f[i + 1][j] + A),f[i][j - 1] + A);
int p = i;
for (int k = 1;k <= j / len;k ++) {
p = pre[p][len];
if (!p) break;
f[p][j] = min(f[p][j],f[i][j] + B + C * (k + 1) + (j - p + 1 - (k + 1) * len) * A);
}
}
cout << f[1][n];
return 0;
}

浙公网安备 33010602011771号