1040 统计单词个数

本文介绍如何统计一段文本中单词的总数,适用于文本处理和数据分析场景。
摘要由CSDN通过智能技术生成
1040 统计单词个数 
 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold

题目描述 Description
给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。
要求将此字母串分成k份(1<k<=40),且每份中包含的单词个数加起来总数最大
(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th) 
(管理员注:这里的不能再用指的是位置,不是字母本身。比如thisis可以算做包含2个is)。
单词在给出的一个不超过6个单词的字典中。
要求输出最大的个数。

输入描述 Input Description
第一行为一个正整数(0<n<=5)表示有n组测试数据
每组的第一行有二个正整数(p,k)
p表示字串的行数;
k表示分为k个部分。
接下来的p行,每行均有20个字符。
再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)
接下来的s行,每行均有一个单词。

输出描述 Output Description
每行一个整数,分别对应每组测试数据的相应结果。



样例输入 Sample Input
1
1 3
thisisabookyouareaoh
4
is
a
ok
sab

样例输出 Sample Output
7

数据范围及提示 Data Size & Hint
"this/isabookyoua/reaoh"

*******************关键是 计算类似前缀和那样的东西 

#include<iostream>
#include<string.h>
#include<cstdio>

using namespace std;

typedef char WORD[210];
WORD dic[6];
int f[210][6];    // f[i][k] 表示字符串中,前i个字母划分k次的最优解 
int w[210][210];
int len[6],ilen[210];
char str[210];

void DP(int n,int k)
{
	int i,j,l;
	for(i = 1; i <= n; i++)     //边界条件 
	{
		f[i][1] = w[1][i];
	}
	for(i = 2; i <= k; i++)
	{
		for(j = i; j <= n; j++)           //从i开始(为什么不是1?) 
		{
			for(l = i; l < j; l++)        //从i开始(为什么不是1?) 
			{
				if(f[j][i] < f[l][i-1] + w[l+1][j])   //为什么不是w[l][j] ?
				{
					f[j][i] = f[l][i-1] + w[l+1][j];
				}
			}
		}
	}
	cout<<f[n][k]<<endl;
}

int main()
{
	int u,n,k,i,j,s,l;
	cin>>u;
	while(u)
	{
		memset(f,0,sizeof(f));
		memset(w,0,sizeof(w));
		memset(ilen,0,sizeof(ilen));
		cin>>n>>k;
		n *= 20;
		for(i = 1; i <= n; i++)
		{
			cin>>str[i];
		}
		cin>>s;
		for(i = 1; i <= s; i++)
		{
			cin>>dic[i];
			len[i] = strlen(dic[i]);
		}
		for(i = 1; i <= n; i++)       //计算str中,字典中单词以第i个字母开头的最短长(贪心)
		{
			for(j = 1; j <= s; j++)
			{
				if( !strncmp(&str[i],dic[j],len[j]) && (!ilen[i] || ilen[i] > len[j]) )
				{
					ilen[i] = len[j];
				}
			}
		}
/*        ilen[] right!
		for(i = 1; i <= n; i++)
		{
			cout<<ilen[i]<<endl;
		}*/
		for(i = 1; i <= n; i++)                    //表示区间ij内的 最多单词包含 数 
		{
			for(j = i; j <= n; j++)
			{
				for(l = i; l <= j; l++)
				{
					if(ilen[l] && ilen[l] <= j-l+1)
					{
						w[i][j]++;
					}
				}
			}
		}
/*		w[][] right!
		for(i = 1; i <= n; i++)
		{
			for(j = i; j <= n; j++)
			{
				cout<<i<<" 到 "<<j<<" : "<<w[i][j]<<endl;
			}
			cout<<endl;
		}*/
		DP(n,k);
		u--;
	}
	return 0;
}



*****************************************************************************可供吐槽

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值