ztr loves substring ( Manacher算法 + 多重背包)

ztr loves substring

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 204    Accepted Submission(s): 112


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
 

Source
BestCoder Round #82 (div.2)


#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
#define esp  1e-8
const double PI = acos(-1.0);
const int inf = 1000000005;
typedef long long ll;
const long long mod = 1000000007;
//freopen("in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
int p[1000], num[1000];
int val[1000005], cnt[1000005], dp[105][105];
char str[1005];
void manacher(char * s)
{
	int len = strlen(s), id = 0;
	memset(p, 0, sizeof(p));
	for (int i = len; i >= 0; --i)
	{
		s[i + i + 2] = s[i];
		s[i + i + 1] = '#';
	}
	s[0] = '*';
	for (int i = 1; i <= 2 * len + 2; ++i)
	{
		if (p[id] + id > i)
			p[i] = min(p[2 * id - i], p[id] + id - i);
		else
			p[i] = 1;
		while (s[i - p[i]] == s[i + p[i]])
			++p[i];
		if (p[i] + i > id + p[id])
			id = i;
		//cout << p[i];
		/*for (int j = 1; j < p[i]; j += 2)
			num[j] ++;*/
		int tt = p[i] - 1;
		while (tt > 0)
		{
			num[tt] ++;
			tt -= 2;
		}
	
	}
	//cout << endl;
}
int main()
{
	int n, k, L, i, j, t;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d%d", &n, &k, &L);
		memset(dp, 0, sizeof(dp));
		memset(num, 0, sizeof(num));
		while (n--)
		{
			scanf("%s", str);
			manacher(str);
		}
		int tot = 0;
		for (int i = 1; i <= 100; ++i)
		{
			int tmp = 1;
			while (num[i] >= tmp)
			{
				val[tot] = tmp * i;
				cnt[tot++] = tmp;
				num[i] -= tmp;
				tmp *= 2;
			}
			if (num[i])
			{
				val[tot] = tmp * i;
				cnt[tot++] = tmp;
			}
		}
		dp[0][0] = 1;
		for (int i = 0; i < tot; ++i)
		{
			for (int j = L; j >= val[i]; --j)
			{
				for (int pp = cnt[i]; pp <= k; ++pp)
				{
					dp[pp][j] |= dp[pp - cnt[i]][j - val[i]];
				}
			}
		}
		if (dp[k][L])
			printf("True\n");
		else
			printf("False\n");

	}
}


 

你可能感兴趣的:(ztr loves substring ( Manacher算法 + 多重背包))