bzoj 2121 字串遊戲

2021-06-28 08:16:08 字數 1266 閱讀 8108

題目大意:給你乙個大字串和乙個字串的集合,每次可以從字串的集合中選出乙個,如果那個大字串中包含了這個字串,就可以從大串中將小串刪掉,刪完後兩邊接起來,求刪完後大串最少剩幾個字元     大串<=150,小串<=20,小串個數<=30

這題沒想著怎麼做,主要還是太弱了。。。

首先可以設f[i][j][k][l]代表第i個到第j個能否刪成第k個小串的前l個字元

那麼當s[j]==s[k][l] 且 f[i][j-1][k][l-1] 時可以f[i][j][k][l]=1,當c[j][k]時,可以f[i][k][x][l]|=f[i][j-1][x][l]    c[j][k]代表j~k可以全部刪完

然後最後的統計就很簡單了,不過因為是bool所以可以壓位,即把f[i][j][k][l]壓成f[i][j][l],k用二進位制表示,這樣可以加快速度

不壓位的

#include#include#include#include#includeusing namespace std;

const int maxn=161,maxm=37,maxl=27;

int q,n,m,len[maxm]; char s[maxn],s[maxm][maxl];

void init()

bool f[maxn][maxm][maxl]; bool c[maxn][maxn];

void getc()

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

int ans[maxn];

void work()

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

}int main()

壓位的

#include#include#include#include#includeusing namespace std;

const int maxn=161,maxm=37,maxl=27;

int q,n,m,len[maxm]; char s[maxn],s[maxm][maxl];

void init()

int f[maxn][maxl],fd[4321]; bool c[maxn][maxn];

void getc() }}

int ans[maxn];

void work()

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

}int main()

bzoj 2121 字串遊戲

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

BZOJ2121 字串遊戲

區間dp 用c l r 表示l r是否能被全部刪掉,f l r k x 表示l r和第k個串匹配是否能匹配到第x位,注意到小串的長度 21,而且f是個bool變數,所以可以把x壓成int,而推一下f的轉移方程發現對於不同的l,他們之間是互不影響的,所以可以把l這一維刪掉 那麼列舉左端點,f r k ...

bzoj2121 字串遊戲

雖然感覺神仙但是又感覺不神仙。對於刪除,一定是刪掉連續的一段的 如果可以預處理出某一段能不能被刪掉,我就很開心了 設f i j k u 表示給出的字串中,i到j和s集合第k個元素第u個字元是否匹配 轉移懶得寫了反正抄的 include include include include include ...