題解 UVA1630 串摺疊 Folding

2021-10-10 23:40:54 字數 1795 閱讀 7122

題目描述

摺疊的定義如下:

乙個字串可以看成它自身的摺疊。記作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。

輸出格式

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

輸入輸出樣例

輸入neercyesyesyesneercyesyesyes

輸出14

說明/提示

乙個最短的摺疊為:2(neerc3(yes))

看完題目和資料範圍,很容易想到這是一道區間dp,即設f[i

][j]

f[i][j]

f[i][j

]表示合併字串第i

ii位到第j

jj位過後的最小長度,那麼該如何轉移這個狀態?

首先講一下我最開始的思路:用乙個陣列min

n[i]

[j

]minn[i][j]

minn[i

][j]

把每乙個狀態得到的字串分別存起來,然後在暴力列舉區間判斷是否相等,但是這種做法會非常麻煩,並且還會超時,因為我們存的是每乙個狀態的字串,不好判斷兩個區間的迴圈節是否相等,所以明顯不行,那麼就再考慮用乙個陣列m[i

][j]

m[i][j]

m[i][j

]把每一種狀態的迴圈節也存下來同時用乙個陣列cir

[i][

j]

cir[i][j]

cir[i]

[j]把每個迴圈節前的係數存下來,這樣就可以省去一層判斷迴圈節是否相等的迴圈.

那麼就可以得出狀態轉移方程

f_=\min(f_+2+(cir_+cir_)的位數),l\le k < r,m_=m_\\f_=\min(f_+f_),l\le k

return res;

}string cov

(int n)

//將乙個數變為字串

reverse

(res.

begin()

, res.

end())

;return res +

"(";

}void

work

(int l,

int k,

int r)

} string temp = minn[l]

[k]+ minn[k +1]

[r];

//另一種情況

if(temp.

length()

< m[l]

[r].

length()

|| m[l]

[r]=="")

//直接合併得到的迴圈節更優

if(temp.

length()

< f[l]

[r])

//轉移狀態

}int

main()

//以上為初始化

for(

int len =

2; len <= n;len++)}

cout << minn[1]

[n]<< endl;

//輸出答案

}return0;

}

UVA 1630 記憶化搜尋

輸入乙個字串,摺疊成乙個盡量短的串。問最短可以摺疊成什麼樣子的乙個串。設dp i j 為字串i到j摺疊成最短的字串後的長度,ss i j 為字串i到j摺疊成的最短的字串。dfs 記憶化搜尋即可。輸入的字串右邊界為str.size 1,需要特別注意。include include include in...

題解 P1630 求和

題目 發現題解都不夠優雅,就自己來一篇 首先,看清楚了,題目是 sum ai b 的餘數 而不是 sum ab i 等比數列求和了解一下 畢竟.本蒟蒻一開始就看錯了.好,進入正題,介於 a,b leq 10 9 暴力就想都不用想了,肯定過不了每一次乘法需要 o b 的時間,加法需要 o a 的時間,...

UVA1630 Folding 區間動態規劃

摺疊乙個字串,使得其成為乙個盡量短的字串 例如aaaaaa變成6 a 而且這個摺疊是可以巢狀的,例如 neeeeeryesyesyesneeeeeryesyesyes 會變成 2 n5 e r3 yes 用dp i j 表示i j壓縮的最小長度dp i j min dp i j dp i k dp ...