HDU 5677 ztr loves substring (dp) - dblank

HDU 5677 ztr loves substring (dp)

Problem Description

ztr love reserach substring.Today ,he has n string.Now ztr want to konw,can he take out exactly k palindrome from all substring of these n string,and thrn sum of length of these k substring is L.

for example string "yjqqaq"
this string contains plalindromes:"y","j","q","a","q","qq","qaq".
so we can choose "qq" and "qaq".

 

Input

The first line of input contains an positive integer T(T<=10) indicating the number of test cases.

For each test case:

First line contains these positive integer N(1<=N<=100),K(1<=K<=100),L(L<=100).
The next N line,each line contains a string only contains lowercase.Guarantee even length of string won't more than L.

 

Output
For each test,Output a line.If can output "True",else output "False".

 

Sample Input
3 2 3 7 yjqqaq claris 2 2 7 popoqqq fwwf 1 3 3 aaa

 

Sample Output
False True True
题意:给你n个字符串,然后你可以选k个这n个字符的回文子串,问这k个子串的长度加起来是否可以为l。
思路:我们可以事先用manachar求出所以回文子串的长度,然后我们记录长度为i的回文子串的个数,然后我们可以利用背包来判断取k个长度是否可以为l,因为这个是多重背包,我们可以用拆分背包来优化时间。dp[i][j]表示取了i个长度为j可以达到否。不过貌似暴力判断回文和直接多重背包都不会超时。
#include<iostream>  
#include<algorithm>  
#include<cstdio>  
#include<queue>  
#include<map>  
#include<vector>  
#include<cstring>  
#include<cmath>  
using namespace std;  
typedef long long ll;  
const int inf =0x3f3f3f3f;  
const double  pi = acos(-1.0);  
const int N = 1e2 + 10;  
char str[N][N][N];  
int dp[N][N], bag[N*N*N], yes[N][N], cnt[N], cnt1[N*N*N];  
void manachar(char *ss)  
{  
    int l = strlen(ss);  
    int len[N*2];  
    memset(len, 0, sizeof(len));  
    for(int i = l; i>=0; i--)  
    {  
        ss[i*2+2] = ss[i];  
        ss[i*2+1] = '#';  
    }  
    ss[0] = '*';  
    int id = 0;  
    for(int i = 1; i<l*2+2; i++)  
    {  
        if(len[id] + id > i)  
            len[i] = min(len[id*2 - i], len[id] + id - i);  
        else len[i] = 1;  
        while(ss[i + len[i]] == ss[i - len[i]]) len[i]++;  
        if(id + len[id] < i + len[i]) id = i;  
        if(ss[i] == '#' && len[i] == 1)continue;  
        cnt[len[i]-1]++;  
    }  
}  
int main()  
{  
    int t;  
    cin>>t;  
    while(t--)  
    {  
        int n, k, l;  
        char s[2*N];  
        scanf("%d%d%d", &n, &k, &l);  
        memset(cnt, 0, sizeof(cnt));  
        memset(dp, 0, sizeof(dp));  
        for(int i = 0; i<n; i++)  
        {  
            scanf("%s", s);  
            manachar(s);  
        }  
        int kk = 0;  
        for(int i = 1; i<=100; i++)  
        {  
            int tmp = 1;  
            while(cnt[i]>=tmp)  
            {  
                bag[kk] = tmp*i, cnt1[kk++] = tmp;  
                cnt[i] -= tmp;  
                tmp*=2;  
            }  
            if(cnt[i])  
                bag[kk] = tmp*i, cnt1[kk++] = tmp;  
        }  
        dp[0][0] = 1;  
        for(int i = 0; i<kk; i++)  
        {  
            for(int j = l; j>=bag[i]; j--)  
            {  
                for(int r = cnt1[i]; r<=k; r++)  
                {  
                    dp[r][j] |= dp[r-cnt1[i]][j - bag[i]];  
                }  
            }  
        }  
        if(dp[k][l])  
            printf("True\n");  
        else printf("False\n");  
    }  
    return 0;  
}

 

相关文章

发表新评论