BZOJ2121 字串遊戲 dp

2022-02-27 16:10:11 字數 1188 閱讀 7518

bzoj2121

dp怎麼那麼神吶qaq

我們要求出最小字串長度

我們設乙個\(dp[i]\)表示前\(i\)個字元最後所形成的最短字串長度

對於第\(i\)個字元,要麼保留,就是\(dp[i] = dp[i - 1] + 1\),要麼和前面若干個字元一起被刪掉

我們設\(c[i][j]\)表示區間\([i,j]\)能否被刪掉

如果我們能求出\(c[i][j]\)就好了

我們再設乙個\(f[i][j][k][t]\)表示區間\([i,j]\)能否匹配第\(k\)個串的前\(t\)個字元

如果存在乙個\(k\),使得\(f[i][j][k][len[k]]\)為真,那麼\(c[i][j]\)就為真

所以我們只需考慮如何求出\(f[i][j][k][t]\)

就是簡單的區間\(dp\)啦

列舉斷點\(d\),然後\(f[i][j][k][l] |= f[i][d][k][t] \&\& c[d + 1][j]\)

注意轉移的順序,因為\(f\)和\(c\)是同時計算的,倒序列舉即可

然後就做完啦

#include#include#include#include#include#define ll long long int

#define redge(u) for (int k = h[u],to; k; k = ed[k].nxt)

#define rep(i,n) for (int i = 1; i <= (n); i++)

#define bug(s,n) for (int i = 1; i <= (n); i++) cout

const int maxn = 155,maxm = 100005,inf = 1000000000;

int f[maxn][maxn][32][23],dp[maxn],c[maxn][maxn],len[32],n,m;

char s[maxn],s[32][23];

int main()

}for (int k = 1; k <= n; k++) c[i][j] |= f[i][j][k][len[k]];

} }for (int i = 1; i <= m; i++)

printf("%d\n",dp[m]);

return 0;

}

bzoj2121 字串遊戲 dp

f i j s t 表示第i個字元到第j個字元能否匹配到第s個串的第t個字元 f i j k t f i j 1 k t 1 s j s k t f i d k t c d 1 j c i j 表示i到j是否能全部刪除 倒序列舉i轉移 好神的dp,感覺自己完全不會dp了 include includ...

bzoj 2121 字串遊戲

題目大意 給你乙個大字串和乙個字串的集合,每次可以從字串的集合中選出乙個,如果那個大字串中包含了這個字串,就可以從大串中將小串刪掉,刪完後兩邊接起來,求刪完後大串最少剩幾個字元 大串 150,小串 20,小串個數 30 這題沒想著怎麼做,主要還是太弱了。首先可以設f i j k l 代表第i個到第j...

bzoj 2121 字串遊戲

bx正在進行乙個字串遊戲,他手上有乙個字串l,以及其他一些字串的集合s,然後他可以進行以下操作 對於乙個在集合s中的字串p,如果p在l中出現,bx就可以選擇是否將其刪除,如果刪除,則將刪除後l 成的左右兩部分合併。舉個例子,l abcdefg s 如果bx選擇將 de 從l中刪去,則刪後的l abc...