洛谷傳送門
BZOJ傳送門
題目描述
給一個由小寫字母組成的字符串,我們可以用一種簡單的方法來壓縮其中的重複信息。壓縮後的字符串除了小寫字母外還可以(但不必)包含大寫字母與,其中標記重複串的開始,重複從上一個(如果當前位置左邊沒有,則從串的開始算起)開始的解壓結果(稱爲緩衝串)。
bcdcdcdcd可以壓縮爲bMcdRR,下面是解壓縮的過程:
已經解壓的部分 | 解壓結果 | 緩衝串 |
---|---|---|
b | b | b |
bM | b | . |
bMc | bc | c |
bMcd | bcd | cd |
bMcdR | bcdcd | cdcd |
bMcdRR | bcdcdcdcd | cdcdcdcd |
輸入輸出格式
輸入格式:
輸入僅一行,包含待壓縮字符串,僅包含小寫字母,長度爲。
輸出格式:
輸出僅一行,即壓縮後字符串的最短長度。
輸入輸出樣例
輸入樣例#1:
aaaaaaa
輸出樣例#1:
5
輸入樣例#2:
bcdcdcdcdxcdcdcdcd
輸出樣例#2:
12
說明
在第一個例子中,解爲aaaRa,在第二個例子中,解爲bMcdRRxMcdRR。
【限制】
50%的數據滿足:
100%的數據滿足:
解題分析
設表示長度爲的前綴的最短長度, 每次我們考慮向後添加一段形如M***R**
的段, 然後轉移。
判字符串是否相等直接用字符串哈希, 然後每次前一半和後一半相同就加上一個, 前面長度減半,然後對答案取。 否則在這段序列後加一個單獨的字母。
總複雜度。
注意特判的情況, 因爲第一段不需要在前面加上。
代碼如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <climits>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define ll long long
#define BASE 233
#define MOD 998244353
#define MX 55
template <class T> IN T max(T a, T b) {return a > b ? a : b;}
template <class T> IN T min(T a, T b) {return a < b ? a : b;}
int len;
int dp[MX], hs[MX], base[MX];
char str[MX];
IN int seg(R int l, R int r) {return (hs[r] - 1ll * hs[l - 1] * base[r - l + 1] % MOD + MOD) % MOD;}
struct INFO {bool typ; int ret;};
IN INFO get(R int l, R int r)
{
int best = INT_MAX, sym = 1, avai = r - l + 1, mid;
W (l < r)
{
mid = l + r >> 1;
W (l < r && seg(l, mid) != seg(mid + 1, r)) --r, mid = l + r >> 1, ++sym;
if (l == r) break;
++sym, r = mid;
best = min(best, sym + r - l + 1);
}
return (best <= avai ? (INFO){false, best} : (INFO){true, avai});
}
int main(void)
{
scanf("%s", str + 1);
len = std::strlen(str + 1);
base[0] = 1;
for (R int i = 1; i <= len; ++i)
{
base[i] = 1ll * base[i - 1] * BASE % MOD;
hs[i] = (1ll * BASE * hs[i - 1] % MOD + str[i]) % MOD;
}
INFO res;
for (R int i = 1; i <= len; ++i)
{
res = get(1, i);
if (!res.typ) dp[i] = res.ret - 1;
else dp[i] = res.ret;
for (R int j = 2; j <= i; ++j)
{
res = get(j, i);
dp[i] = min(dp[i], dp[j - 1] + res.ret);
}
}
printf("%d\n", dp[len]);
}