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.
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 "); 56 else printf("False "); 57 } 58 }