标签:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 /** 6 7 8 manacher 处理出回文串长度 9 p[i]:半径 10 11 if(s[i] == ‘#‘ && p[i] == 1) continue; 12 else{ 13 int tmp = p[i] / 2; 14 if(s[i] == ‘#‘) for(int i = 2 ; i <= tmp ; i += 2) cnt[i]++; 15 else for(int i = 1 ; i <= tmp ; i += 2) cnt[i]++; 16 } 17 18 问题就变成 : 有 n 种 大小不同的数字 a[i] , 每种 mi个,是否可以选出k个和为l 19 背包问题: 20 a[i] : 第i个数的值为 a[i]; 21 m[i] : 第i个数的个数为 m[i]; 22 23 memset(dp,0,sizeof(dp)); 24 dp[0][0] = 1; 25 for(int i = 0 ; i < t ; i ++){ 26 for(int j = l ; j >= a[i] ; j --){ 27 for(int jj = m[i] ; jj <= k ; jj ++){ 28 dp[jj][j] |= dp[jj-m[i]][j-a[i]]; 29 } 30 } 31 } 32 33 */ 34 35 36 const int MAX=100+10; 37 int p[MAX*2]; 38 int cnt[MAX*2]; 39 int a[MAX*2],m[MAX*2]; 40 int dp[110][110]; 41 int n,k,l,t; 42 void manacher(char *s){ 43 int len=strlen(s),id=0,maxlen=0; 44 for(int i=len;i>=0;--i){//插入‘#‘ 45 s[2*i+2]=s[i]; 46 s[2*i+1]=‘#‘; 47 } 48 s[0]=‘*‘; 49 for(int i=2;i<2*len+1;++i){ 50 if(p[id]+id>i) p[i]=min(p[2*id-i],p[id]+id-i); 51 else p[i]=1; 52 while(s[i-p[i]] == s[i+p[i]]) ++p[i]; 53 if(id+p[id]<i+p[i]) id=i; //记录最长延伸点 54 // if(maxlen<p[i]) maxlen=p[i]; 55 56 if(s[i] == ‘#‘ && p[i] == 1) continue; 57 else{ 58 // cout << i << " " << p[i] << endl; 59 int tmp = p[i] ; 60 if(s[i] == ‘#‘) for(int j = 2 ; j <= p[i]-1 ; j += 2) cnt[j]++; 61 else for(int j = 1 ; j <= p[i]-1 ; j += 2) cnt[j]++; 62 } 63 } 64 } 65 66 int main(){ 67 68 int T; 69 scanf("%d",&T); 70 char str[110*2]; 71 while(T--){ 72 memset(a,0,sizeof(a)); 73 memset(m,0,sizeof(m)); 74 memset(cnt,0,sizeof(cnt)); 75 memset(dp,0,sizeof(dp)); 76 77 scanf("%d%d%d",&n,&k,&l); 78 for(int i = 0 ; i < n ; i ++){ 79 scanf("%s",str); 80 manacher(str); 81 } 82 /** 83 例如 值为10的个数为cnt = 7; 84 可以拆成值为 10 的个数为 1,2,4; 选六个只需选择其中的2,4 85 */ 86 t = 0; 87 for(int i = 0 ; i <= 100 ; i ++){ 88 int tmp = 1; 89 while(cnt[i] >= tmp){ 90 a[t] = tmp*i , m[t++] = tmp; 91 cnt[i] -= tmp; 92 tmp *= 2; 93 } 94 if(cnt[i]){ 95 a[t] = cnt[i]*i , m[t++] = cnt[i]; 96 } 97 } 98 99 /** 100 a[i] : 第i个数的值为 a[i]; 101 m[i] : 第i个数的个数为 m[i]; 102 */ 103 memset(dp,0,sizeof(dp)); 104 dp[0][0] = 1; 105 for(int i = 0 ; i < t ; i ++){ 106 for(int j = l ; j >= a[i] ; j --){ 107 for(int jj = m[i] ; jj <= k ; jj ++){ 108 dp[jj][j] |= dp[jj-m[i]][j-a[i]]; 109 } 110 } 111 } 112 113 if(dp[k][l]) printf("True\n"); 114 else printf("False\n"); 115 } 116 117 return 0; 118 }
hdu 5677 ztr loves substring(manacher,背包问题)
标签:
原文地址:http://www.cnblogs.com/zstu-jack/p/5450861.html