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...