HDOJ-5677 ztr loves substring

用manacher 求出每个串的所有子串长度,然后把每个子串当作物品,费用为长度,和个数,就可以当作二维费用的多重背包来解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100005
using namespace std;

bool dp[105][105]; 
int p[105], len[105<<1];
char str[105], ans[105<<1];
void Manacher(){

    int mex = 0, id;
    for(int i = 1; ans[i]; i++){

        if(mex > i)
          len[i] = min(len[2*i-id], mex-i);
        else
         len[i] = 1;
        while(ans[i+len[i]] == ans[i-len[i]])
          len[i]++;
        if(mex < i + len[i]){
            id = i;
            mex = i + len[i];
        }
    }
    for(int i = 1; ans[i]; i++){
           for(int j = len[i]-1; j > 0; j -= 2)
             p[j]++;
    }
}
void Init(){

    scanf("%s", str);
    int d = 1;
    ans[0] = '@';
    for(int i = 0; str[i]; i++){
        ans[d++] = '#';
        ans[d++] = str[i];
    }
    ans[d++] = '#';
    ans[d] = 0;

    Manacher();
}

int main(){

// freopen("in.txt", "r", stdin);
    int t;

    cin >> t;
    while(t--){

        int n, k, l;

        scanf("%d%d%d", &n, &k, &l);
        memset(p, 0, sizeof(p));
        memset(dp, false, sizeof(dp));
        for(int i = 0; i < n; i++)
         Init();
        dp[0][0] = true;
        for(int i = 1; i <= l; i++){
          int h;
          for(h = 1; h <= p[i]; h << 1, p[i] -= h)
           for(int j = l; j >= h*i; j--)
           for(int e = h; e <= k; e++){
              dp[j][e] |= dp[j-h*i][e-h];
           }
          if(p[i]){
            h = p[i];
          for(int j = l; j >= i*h; j--)
           for(int e = h; e <= k; e++)
            dp[j][e] |= dp[j-i*h][e-h];
           }
        }

        if(dp[l][k])
         cout << "True" << endl;
        else
         cout << "False" << endl;
    }
    return 0;
}

你可能感兴趣的:(HDOJ-5677 ztr loves substring)