Codevs_1040_[NOIP2001]_统计单词个数_(划分型动态规划)
描述
http://codevs.cn/problem/1040/
与Codevs_1017_乘积最大很像,都是划分型dp.
给出一个字符串和几个单词,要求将字符串划分成k段,在每一段中求共有多少单词(两个单词不能共享第一个字母),将每一段中的单词个数相加,求最大值.
1040 统计单词个数
2001年NOIP全国联赛提高组
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
分析
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxl=200+5,maxk=40+5,maxd=10; 5 int n,p,K,s,len; 6 int a[maxl][maxl],dp[maxl][maxl]; 7 char str[maxl],dic[maxd][maxl]; 8 9 bool match(int l,int r){ 10 for(int i=1;i<=s;i++){ 11 int len=strlen(dic[i]+1); 12 if(len>r-l+1) continue; 13 bool flag=true; 14 for(int j=1;j<=len;j++) 15 if(str[l-1+j]!=dic[i][j]) { 16 flag=false; 17 break; 18 } 19 if(flag) return true; 20 } 21 return false; 22 } 23 void pre(){ 24 memset(a,0,sizeof a); 25 for(int i=1;i<=len;i++){ 26 if(match(i,i)) a[i][i]=1; 27 for(int j=i-1;j;j--){ 28 if(match(j,i)) a[j][i]=a[j+1][i]+1; 29 else a[j][i]=a[j+1][i]; 30 } 31 } 32 } 33 void solve(){ 34 pre(); 35 for(int i=1;i<=len;i++) dp[i][1]=a[1][i]; 36 for(int k=2;k<=K;k++) 37 for(int i=k;i<=len;i++) 38 for(int j=k-1;j<i;j++) 39 dp[i][k]=max(dp[i][k],dp[j][k-1]+a[j+1][i]); 40 printf("%d\n",dp[len][K]); 41 } 42 void init(){ 43 scanf("%d%d\n",&p,&K); 44 int id=0; 45 for(int i=1;i<=p;i++){ 46 char c; c=getchar(); 47 while(c>='a'&&c<='z'){ 48 str[++id]=c; 49 c=getchar(); 50 } 51 } 52 len=id; 53 scanf("%d",&s); 54 for(int i=1;i<=s;i++) scanf("%s",dic[i]+1); 55 } 56 int main(){ 57 freopen("tjdcgs.in","r",stdin); 58 freopen("tjdcgs.out","w",stdout); 59 scanf("%d",&n); 60 while(n--){ 61 init(); 62 solve(); 63 } 64 return 0; 65 }