标签:
题目链接: hdu 5677 ztr loves substring
官方题解:
//这部分是错的(首先,对于每一个串i跑一次manancher,令g[i][j]=p[j]-1g[i][j]=p[j]−1
这样,g就存储了所有的回文子串的长度
为了方便,把g降到一维表示)
首先,因为字符串长度较小,所以直接二重for循环找就好了,用一个数组 g记录各个回文串的长度
不妨把每一个子串抽象成一个物品
费用为二维的,即{长度,1}
价值是Bool型的
这样就成了一个二维判断可行性费用背包问题
设f(i,j)f(i,j)表示当前选出的长度为i,已经选了j个串,这个状态能否达到
f(i,j)=f(i,j)|f(i-g(k),j-1)f(i,j)=f(i,j)∣f(i−g(k),j−1)
这样,时间复杂度为O(L*K*N^{2})O(L∗K∗N?2??)
显然还是过不去
我们分析,发现其实g是会大量重复的
那么不妨当做多重背包来处理
时间复杂度降为O(L*K*N*log\sum Li)O(L∗K∗N∗log∑Li)
/************************************************************** Problem:hdu 5677 User: youmi Language: C++ Result: Accepted Time:31MS Memory:2264K ****************************************************************/ //#pragma comment(linker, "/STACK:1024000000,1024000000") //#include<bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <stack> #include <set> #include <sstream> #include <cmath> #include <queue> #include <deque> #include <string> #include <vector> #define zeros(a) memset(a,0,sizeof(a)) #define ones(a) memset(a,-1,sizeof(a)) #define sc(a) scanf("%d",&a) #define sc2(a,b) scanf("%d%d",&a,&b) #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scs(a) scanf("%s",a) #define sclld(a) scanf("%I64d",&a) #define pt(a) printf("%d\n",a) #define ptlld(a) printf("%I64d\n",a) #define rep0(i,n) for(int i=0;i<n;i++) #define rep1(i,n) for(int i=1;i<=n;i++) #define rep_1(i,n) for(int i=n;i>=1;i--) #define rep_0(i,n) for(int i=n-1;i>=0;i--) #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define lson (step<<1) #define rson (lson+1) #define esp 1e-6 #define oo 0x3fffffff #define TEST cout<<"*************************"<<endl using namespace std; typedef long long ll; int n,K,L; const int maxn=200+10; char s[maxn]; char p[maxn<<1]; int dp2[maxn<<1]; int str[maxn<<1]; int dp[maxn<<1][maxn<<1]; void manacher(int len) { int l=0; p[l++]=‘$‘; p[l++]=‘#‘; for(int i=0;i<len;i++) { p[l++]=s[i]; p[l++]=‘#‘; } p[l]=0; int mx=0,id=0; for(int i=0;i<l;i++) { dp2[i]=mx>i?Min(dp2[2*id-i],mx-i):1; while(p[dp2[i]+i]==p[i-dp2[i]]) dp2[i]++; if(mx<dp2[i]+i) { id=i; mx=dp2[i]+i; } } } int check(int l,int r) { for(int i=l,j=r;i<=j;i++,j--) if(s[i]!=s[j]) return 0; return 1; } void zeroone(int len,int num) { for(int i=L;i>=len;i--) for(int j=K;j>=num;j--) if(dp[i-len][j-num]) dp[i][j]++; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif int T_T; scanf("%d",&T_T); for(int kase=1;kase<=T_T;kase++) { sc3(n,K,L); zeros(str); rep0(i,n) { scs(s); int len=strlen(s); /**manacher(len); for(int i=2;i<=2*len;i+=2) str[dp2[i]-1]++,mx=Max(mx,dp2[i]-1);*/ for(int i=0;i<len;i++) for(int j=i;j<len;j++) if(check(i,j)) str[j-i+1]++; } zeros(dp);//下面就是二维背包了 dp[0][0]=1; for(int i=1;i<=L;i++) { if(str[i]==0) continue; int cnt=1; while(cnt<str[i]) { zeroone(i*cnt,cnt); str[i]-=cnt; cnt<<=1; } zeroone(i*str[i],str[i]); } puts(dp[L][K]?"True":"False"); } }
hdu 5677 ztr loves substring 二维费用背包+回文
标签:
原文地址:http://www.cnblogs.com/youmi/p/5453492.html