[HDU5677]ztr loves substring

ztr loves substring

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

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
 
题解:
(多重背包都快不会打了我已经完蛋了)
这道题相对来说还是比较裸的。先用manacher计算出每种长度回文串出现的个数。
在将长度视为物品跑一个多重背包即可。
关于这里的背包,我们可以设f[i][j]为一个bool滚动数组,表示构造长度为i的串用了j个子串能不能成立。
那么显然3层循环即可。我打的是二进制分解然后01背包(其实是因为单调队列不会)
代码见下:
 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int N=110;
 5 int n,t,m,k,ct,mx,l;
 6 int r[N<<1],f[N][N],vis[N];
 7 char s[N<<1],str[N];
 8 inline int max(int a,int b){return a>b?a:b;}
 9 inline int min(int a,int b){return a<b?a:b;}
10 inline void manacher()
11 {
12     memset(s,0,sizeof(s));
13     n=0;m=strlen(str);
14     s[n++]=1;s[n++]=2;
15     for(int i=0;i<m;i++)s[n++]=str[i],s[n++]=2;
16     memset(r,0,sizeof(r));ct=mx=0;
17     for(int i=0;i<n;i++)
18     {
19         if(i<mx)r[i]=min(mx-i,r[2*ct-i]);
20         else r[i]=1;
21         while(0<=i-r[i]&&i+r[i]<n&&s[i-r[i]]==s[i+r[i]])r[i]++;
22         if(i+r[i]>mx)ct=i,mx=i+r[i];
23         int j=r[i]-1;
24         while(j>=0)vis[j]++,j-=2;
25     }
26 }
27 int c[N*N],v[N*N],cnt;
28 inline bool backpack()
29 {
30     memset(f,0,sizeof(f));
31     for(int i=1;i<=l;i++)
32     {
33         int tmp=1;
34         while(vis[i]>=tmp)
35             c[++cnt]=tmp*i,v[cnt]=tmp,vis[i]-=tmp,tmp<<=1;
36         if(vis[i])
37             c[++cnt]=vis[i]*i,v[cnt]=vis[i];
38     }
39     f[0][0]=1;
40     for(int u=1;u<=cnt;u++)
41         for(int i=l;i>=c[u];i--)
42             for(int j=k;j>=v[u];j--)
43                 f[i][j]|=f[i-c[u]][j-v[u]];
44     return f[l][k];
45 }
46 int main()
47 {
48     int cnt;scanf("%d",&cnt);
49     while(cnt--)
50     {
51         scanf("%d%d%d",&t,&k,&l);
52         memset(vis,0,sizeof(vis));
53         for(int i=1;i<=t;i++)
54             scanf("%s",str),manacher();
55         if(backpack())printf("True\n");
56         else printf("False\n");
57     }
58 }
HDU5677
posted @ 2017-07-09 21:20  LadyLex  阅读(221)  评论(0编辑  收藏  举报