noip2001提高 统计单词个数

题目:https://www.luogu.org/problemnew/show/P1026

给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成kk份(1<k \le 401<k≤40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。

单词在给出的一个不超过6个单词的字典中。

要求输出最大的个数。

 

对于字符串string函数处理:https://user.qzone.qq.com/1243296256/infocenter?_t_=0.8054686899343291

 

预处理一波单词个数以后就可以dp了

状态转移方程:

f[i][k]=max(f[i][k],f[j][k-1]+a[j+1][i]);

 

注意!!!

最后的循环要注意j>=0 ,也不能盲目max(0,k-2);会出错!!!

代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>

using namespace std;

int p,k1,t,len;
string s,zd[10];
long long f[200+5][45],a[205][205];

int main()
{
	int i,j,k;
	string s1;
	
	freopen("a.txt","r",stdin);
	memset(f,0,sizeof(f));
	memset(a,0,sizeof(a));
	cin>>p>>k1;
	s="";	len=20*p;
	for (i=0;i<p;i++)
	{
		cin>>s1;
		s=s+s1;
	}
	cin>>t;
	for (i=0;i<t;i++)
		cin>>zd[i];
//	cout<<s.find("isa",0);
//	cout<<s.substr(1,2);
//	cout<<s;
	for (j=len-1;j>=0;j--)
	{
		for (i=j;i>=0;i--)
		{
			s1=s.substr(i,j-i+1);
//			if (i==0 && j==1)
//				cout<<s1<<endl;
			
			a[i][j]=a[i+1][j];
			for (k=0;k<t;k++)
			{
				if (s1.find(zd[k],0)==0)
				{
					a[i][j]++;
					break;
				}
			}
		}
	}
	for (i=0;i<len;i++)
	{
		for (k=1;k<=min(i+1,k1);k++)
		{
//			if (i==199 && k==4)
//				printf("zbk");
				
			for (j=k-2;j<i;j++)
			{
				int j1=max(j,0);
				f[i][k]=max(f[i][k],f[j1][k-1]+a[j+1][i]);
			}
		}
	}
	cout<<f[len-1][k1]<<endl;
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值