Live2d Test Env

BZOJ2121: 字符串游戏(DP)(字符串删单词,求最多可以删去多少)

2121: 字符串游戏

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 672  Solved: 376
[Submit][Status][Discuss]

Description

BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对
于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删除,如果删除,则将删除后L分裂成的左右
两部分合并。举个例子,L='abcdefg' , S={'de'},如果BX选择将'de'从L中删去,则删后的L='abcfg'。现在BX可
以进行任意多次操作(删的次数,顺序都随意),他想知道最后L串的最短长度是多少。

Input

输入的第一行包含一个字符串,表示L。
第二行包含一个数字n,表示集合S中元素个数。
以下n行,每行一个字符串,表示S中的一个元素。
输入字符串都只包含小写字母。

Output

输出一个整数,表示L的最短长度。

Sample Input

aaabccd
3
ac
abc
aaa

Sample Output

2
【样例说明】
aaabccd
aacd
ad
对于100%数据,满足|L|<151,|S|<31,S中的每个元素|p|<21

HINT

Source

思路:我们用f[i][j][k][l]表示第[i,j]这个区间能否删成第k个单词的前l位,用cov[i][j]表示[i,j]这个区间能否被完全删去。

复杂度O(N^3*S*p);

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=155;
int f[maxn][maxn][35][25],cov[maxn][maxn],dp[maxn];
char c[maxn],s[35][25]; int Len[35];
int main()
{
    int N,M;
    scanf("%s",c+1); N=strlen(c+1);
    scanf("%d",&M);
    for(int i=1;i<=M;i++){
        scanf("%s",s[i]+1);
        Len[i]=strlen(s[i]+1);
    }
    rep(i,1,N) rep(j,1,M) f[i][i-1][j][0]=1; //匹配的时候需要边界条件
    rep(len,1,N)
     rep(L,1,N-len+1){
        int R=L+len-1;
        rep(i,1,M){
            rep(j,1,Len[i]) if(c[R]==s[i][j]) f[L][R][i][j]|=f[L][R-1][i][j-1]; //匹配
            rep(j,0,Len[i]) rep(k,L+1,R) //不匹配
                f[L][R][i][j]|=(f[L][k-1][i][j]&cov[k][R]);
        }
        rep(i,1,M) cov[L][R]|=f[L][R][i][Len[i]];
     }
    rep(i,1,N){ //背包得到最大值
        rep(j,1,i) if(cov[j][i]) rep(k,i,N) dp[k]=max(dp[k],dp[j-1]+i-j+1);
        rep(j,i+1,N) dp[j]=max(dp[j],dp[j-1]);
    }
    printf("%d\n",N-dp[N]);
    return 0;
}

 把int换成bool快了一倍,word天啦。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=155;
bool f[maxn][maxn][35][25],cov[maxn][maxn];
char c[maxn],s[35][25];int Len[35],dp[maxn];
int main()
{
    int N,M;
    scanf("%s",c+1); N=strlen(c+1);
    scanf("%d",&M);
    for(int i=1;i<=M;i++){
        scanf("%s",s[i]+1);
        Len[i]=strlen(s[i]+1);
    }
    rep(i,1,N) rep(j,1,M) f[i][i-1][j][0]=1; //匹配的时候需要边界条件
    rep(len,1,N)
     rep(L,1,N-len+1){
        int R=L+len-1;
        rep(i,1,M){
            rep(j,1,Len[i]) if(c[R]==s[i][j]) f[L][R][i][j]|=f[L][R-1][i][j-1]; //匹配
            rep(j,0,Len[i]) rep(k,L+1,R) //不匹配
                f[L][R][i][j]|=(f[L][k-1][i][j]&cov[k][R]);
        }
        rep(i,1,M) cov[L][R]|=f[L][R][i][Len[i]];
     }
    rep(i,1,N){ //背包得到最大值
        rep(j,1,i) if(cov[j][i]) rep(k,i,N) dp[k]=max(dp[k],dp[j-1]+i-j+1);
        rep(j,i+1,N) dp[j]=max(dp[j],dp[j-1]);
    }
    printf("%d\n",N-dp[N]);
    return 0;
}

 

posted @ 2018-12-03 09:21  nimphy  阅读(336)  评论(0编辑  收藏  举报