字串摺疊 壓縮(區間DP)

2022-03-29 15:10:32 字數 3265 閱讀 9192

字串摺疊

摺疊的定義如下:

乙個字串可以看成它自身的摺疊。記作s = s

x(s)是x(x>1)個s連線在一起的串的摺疊。記作x(s) = ssss…s(x個s)。

如果a = a』, b = b』,則ab = a』b』 例如,因為3(a) = aaa, 2(b) = bb,所以3(a)c2(b) = aaacbb,而2(3(a)c)2(b) = aaacaaacbb

給乙個字串,求它的最短摺疊。例如aaaaaaaaaabababccd的最短摺疊為:9(a)3(ab)ccd。

僅一行,即字串s,長度保證不超過100。

僅一行,即最短的摺疊長度

emmmmm,首先題意上說明摺疊後的長度是加上數字的長度和括號的,  設f[l][r]表示將區間[l, r]摺疊後的最小長度, 顯然初值是r - l + 1;然後我們去暴力列舉該區間可以有哪兩個區間去合併, 然後就該考慮到它自身摺疊的問題了, 可以暴力列舉它每一段的長度, 然後判斷是否可以摺疊, 設此時列舉長度為k且可以合併, 那麼顯然$f[l][r] = min(f[l][r], f[l][l + k - 1] + 2 + a[len / k]);$, 2為括號的長度, a陣列表示數字的長度, 即1長度為1 , 10長度為10等, 最後直接輸出f[1][n]即可, 思路應該很清晰, 這道題還是比較水的(吧。。。)

#include using

namespace

std;

typedef

long

long

ll;const

int inf = 0x3f3f3f3f

;const

int maxn = 5e5 + 100

;const

int maxm = 1e3 + 10

;const

double eps = 1e-5

;template

< typename t > inline void read(t &x)

while

(isdigit(ch))

x *=ff;

}template

< typename t > inline void

write(t x)

if(x < 0) putchar('

-'), x = -x;

static t tot = 0, ch[30

];

while

(x)

while(tot) putchar(ch[tot--]);

} int n, a[110], f[110][110

];char ch[110

]; inline

bool check(int l, int r, int

len)

return

true;}

intmain()

for (int len = 2; len <= n; ++len) }}

write(f[

1][n]);

return0;

}

view code

壓縮給乙個由小寫字母組成的字串,我們可以用一種簡單的方法來壓縮其中的重複資訊。壓縮後的字串除了小寫字母外還可以(但不必)包含大寫字母r與m,其中m標記重複串的開始,r重複從上乙個m(如果當前位置左邊沒有m,則從串的開始算起)開始的解壓結果(稱為緩衝串)。

bcdcdcdcd可以壓縮為bmcdrr,下面是解壓縮的過程:

已經解壓的部分

解壓結果

緩衝串bbb

bmb.bmcbcc

bmcd

bcdcd

bmcdr

bcdcd

cdcd

bmcdrr

bcdcdcdcd

cdcdcdcd

輸入僅一行,包含待壓縮字串,僅包含小寫字母,長度為n。

輸出僅一行,即壓縮後字串的最短長度。

剛看到這道題, ??雙倍經驗??也就瞎寫一波, 狀態方法都是一樣的, f[l][r]表示將區間[l, r]摺疊的最短長度,當l等於1的時候特判第乙個m就不需要了, 應該沒問題, 嗯呢, 提交, 60, 好慘。。。可以用一組資料hack這個做法: aaaaaaaaaa, 最好的情況顯然是5(aarar), 但這個程式跑出來確實是6, 是因為r複製的是在它之前的第乙個m, 所以r也會複製到r, 這樣你就無法判斷了, 所以r對應的m在哪就是乙個需要解決的問題。 我們不妨開乙個三維的陣列, f[l][r][0]表示摺疊[l ,r]且之間沒有m的最短長度, 預設l - 1是m, f[l][r]][1]就表示之間有m, 對於每個m出現的位置, 我們也可以暴力去判斷出現在**是最優的情況, 這樣時間複雜度為$o(n^3)$, 輸出$\min(f[1][n][0], f[1][n][1])$即可。

#include using

namespace

std;

typedef

long

long

ll;const

int inf = 0x3f3f3f3f

;const

int maxn = 5e5 + 100

;const

int maxm = 1e3 + 10

;const

double eps = 1e-5

;template

< typename t > inline void read(t &x)

while

(isdigit(ch))

x *=ff;

}template

< typename t > inline void

write(t x)

if (x < 0) putchar('

-'), x = -x;

static t tot = 0, ch[30

];

while

(x)

while (tot) putchar(ch[tot--]);

} int n, a[110], f[60][60][2

];char ch[60

]; inline

bool check(int l, int

r)

return

true;}

intmain()

for (int len = 2; len <= n; ++len)

}write(min(f[

1][n][0], f[1][n][1

]));

return0;

}

view code

字串摺疊 區間dp

摺疊的定義如下 乙個字串可以看成它自身的摺疊。記作s s x s 是x x 1 個s連線在一起的串的摺疊。記作x s ssss s x個s 如果a a b b 則ab a b 例如,因為3 a aaa,2 b bb,所以3 a c2 b aaacbb,而2 3 a c 2 b aaacaaacbb ...

SCOI 2003 字串摺疊(區間 dp)

求乙個字串的最短可巢狀壓縮長度。如aaaaaaaaaabababccd最短為9 a 3 ab ccd。1 s 100 1 leq s leq 100 1 s 100對於乙個字串,令 fi,jf fi,j 為 i,j i,j i,j 的最短壓縮長度,有三個壓縮。原串形式,將 fi,jf fi,j 賦初...

SCOI2003 字串摺疊(區間dp)

摺疊的定義如下 乙個字串可以看成它自身的摺疊。記作s s x s 是x x 1 個s連線在一起的串的摺疊。記作x s ssss s x個s 如果a a b b 則ab a b 例如,因為3 a aaa,2 b bb,所以3 a c2 b aaacbb,而2 3 a c 2 b aaacaaacbb ...