您的位置:首页 > 其它

HDOJ-5677 ztr loves substring

2016-05-01 16:23 357 查看
用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: