洛谷P1026&NOIP2001 统计单词个数

本文介绍了一种使用动态规划解决字符串划分问题的方法。通过预处理数组记录子串中不同单词的数量,利用DP状态转移方程求解最优解。适用于需要高效处理大量字符串数据的应用场景。

刚看到这个题一直在纠结怎么划分成k份再转移,事实证明我想多了

先预处理出数组w[I][j],表示从i到j的单词个数,如果有多个以i开头的单词,只统计一次即可

dp[I][j]表示从0到i划分成j份,则

dp[I][j]=max(dp[k][j-1]+w[k+1][j]|j-1<=k<i)

顺便%一下用贪心A掉此题的ZY大神


#include<iostream>
#include<cstring>
#include<string>
#define f dp
#define maxn 200+2
#define maxk 40+2
#define maxs 6+2 
using namespace std;
string dic[maxs],a;
int p,k,s,dp[maxn][maxk];//表示从0到i分成j份 
int w[maxn][maxn];//表示从i到j有w[i][j]个单词 
void init(void){
	cin>>p>>k;
	string temp;
	a+='0';
	for(int i=0;i<p;i++){
		cin>>temp;
		a+=temp;
	}
	cin>>s;
	for(int i=1;i<=s;i++)
		cin>>dic[i];
	memset(dp,0,sizeof(dp));
	memset(w,0,sizeof(w));
	for(int i=p*20;i>0;i--){
		for(int j=i;j<=p*20;j++){//枚举字符 
			for(int k0=1;k0<=s;k0++){//枚举单词 	
				if(a.find(dic[k0],i)==i&&dic[k0].length()<=j-i+1){
					w[i][j]++;
					break;
				}
			}
			w[i][j]+=w[i+1][j];
		}
	}
	/*for(int i=1;i<=p*20;i++){
		dp[i][i]=
	}*/
	return;
}
int main(){
	init();
	//dp[i][j]=max(dp[k][j-1]+w[k+1]|k>=j-1) 
	for(int i=1;i<=p*20;i++){
		for(int j=1;j<=i&&j<=k;j++){
			int temp=0;
			for(int k0=j-1;k0<i;k0++)
				temp=max(temp,dp[k0][j-1]+w[k0+1][i]);
			dp[i][j]=temp;
		}
	}
	cout<<dp[p*20][k];
	return 0;
} 


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值