字串摺疊
摺疊的定義如下:
乙個字串可以看成它自身的摺疊。記作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 usingview codenamespace
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;
}
壓縮給乙個由小寫字母組成的字串,我們可以用一種簡單的方法來壓縮其中的重複資訊。壓縮後的字串除了小寫字母外還可以(但不必)包含大寫字母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 usingview codenamespace
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;
}
字串摺疊 區間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 ...