摺疊的定義如下:
乙個字串可以看成它自身的摺疊。記作 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。
設 \(f[i][j]\) 表示 \([i,j]\) 這一段的最小摺疊。那麼 \(f[i][j]\) 可能會有兩種轉移:
列舉乙個中間點 \(k\),\(f[i][j]=\min(f[i][k]+f[k+1][j])\)。
列舉乙個中間點 \(k\),\([i\sim k]\) 正好是 \((k\sim j]\) 的字首,且可以經過若干次自我複製得到 \((k\sim j]\)。
對於第二個轉移,我們需要在較優秀複雜度內判斷一段區間是否是另一段區間字首且可以自我複製變成另一段區間。用字串 hash 亂搞即可。
時間複雜度 \(o(n^3)\)。
#include using namespace std;
typedef unsigned long long ull;
const int n=110;
const ull base=131;
int n,f[n][n],cnt[n];
ull power,g[n][n],hash[n][n];
char ch[n];
int main()
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j++)
hash[i][j]=hash[i][j-1]*base+ch[j];
for (int i=n;i>=1;i--)
for (int j=i+1;j<=n;j++)
for (int k=i;kprintf("%d",f[1][n]);
return 0;
}
P4302 SCOI2003 字串摺疊
演算法 區間動態規劃 f i j f i j f i j 表示處理i到j i到ji到 j這段區間所需要的最小代價 兩種轉移方法 一.標準的區間dpdp dp的轉移f i j min f i j f i k f k 1 j f i j min f i j f i k f k 1 j f i j mi ...
P4302 SCOI2003 字串摺疊
摺疊的定義如下 乙個字串可以看成它自身的摺疊。記作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 ...
luogu4302字串摺疊題解 區間DP
很明顯一道區間dp題,對於區間 l,r 的字串,如果它的字串是最優摺疊的,那麼它的最優結果要麼是所有分割出的字串最優結果之和,要麼是在斷點處恰好有這個區間的週期串可以進行摺疊,摺疊後產生的結果 狀態轉移 for ri len 2 len n len const int maxn 205 int n,...