1026 统计单词

1026 统计单词

首先我们要记住一个小常识,就是通过字符串的加法可以将两个字符串相互连接
还有就是区间的枚举,头尾不固定,每一个也不是固定,所以我们需要一个三次方的循环,说白了就是一个暴力枚举,其实就是类似于弗洛伊德的枚举

我看了半天还没看明白这是什么意思,也许这个题是一个dp

分成k份,且每份中包含的单词个数加起来总数最大
定义一个dp数组[i][j]表示到i个字符分割成j段的最大结果
方程就是dp[i][j]=dp[k][j-1]+sum[k+1][i]
意思就是处理好每一段单词个数,然后区间dp,两个步骤
所以说这个题真的好麻烦啊,要搞的东西真的非常的多,老子今年 第一张就这么难,沃夫了
统计区间内单词的数量,只有进行暴力枚举
然后就是动态规划的处理
这个是精髓
f[i][1]=sum[0][i]初始化,至于为什么,为什么?分割成一段也就是他自己的本身,也就是自己这本身的单词数量
然后接着规划
---------------重新-------------------

首先,先说说题意是什么意思
给定p个字符串
然后给出一个字典序
这个字典序中有单词,然后将上面的字符串进行分割,看看怎么分割使得单词最大,最大是多少
不用想,这是一个dp
首先,我们输入的这些字符串,直接当成一个就好,把字符串连接起来,这样方便
开头是i,然后从i往后循环j就是结尾,这样就能一个单词,然后再循环一个k的分割
字符串的分割,然后将单词进行比较
套了好几层的循环,说白了就是模拟
这个题说白了就是一个暴力,也没有什么算法,sum[i][j]就是一个记录最大单词数量的
sum数组只是做了一个前缀,一个铺垫
f[i][1]=sum[0][i]就是本身的数量,不需要分割
dp数组[i][j]表示到i个字符分割成j段的最大结果

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string> 
using namespace std;
int n,m,s,len;
int sum[205][205],lenth[11],f[205][55];
string a,b;
string ss[11];
inline void work()//步骤1 
{
	for(int i=0;i<len;i++)//枚举开头 
		for(int j=i;j<len;j++)//枚举结尾  枚举开头结尾 
			for(int k=i;k<=j;k++)//模拟分割的 
			//枚举分割,判断分割的最大  分割出来的单词 
			{
				int flag=1;//类似于标记 
				for(int l=1;l<=s;l++)//枚举每一个单词  进行比较 
				///这个循环就是用来比较单词数量的 
				{
					if(k+lenth[l]-1>j) continue;//小剪枝,长度不够肯定不需要枚举了
					//长度不够没有进行下去的必要了 
					//这个不只是剪纸的问题 
					for(int w=0;w<lenth[l];w++)//获得单词 
					{
						if(w==lenth[l]-1&&a[k+w]==ss[l][w])//a存的是字符串
						//用来暴力枚举去区间内的,相同的话 
						//枚举k份 
						{
							flag=0;//进行标记 
							break;
						}
						if(a[k+w]!=ss[l][w]) break;//直接退出,有一个不符合就不行 
					}
					if(flag==0) break;//已经找到了 不需要接着往下进行了 
				}
				if(flag==0) sum[i][j]++;//统计区间内的单词数量  将区间内的单词数量存入 
			}
}	

inline void solve()//步骤1 
{
	for(int i=0;i<len;i++)
	{
		f[i][1]=sum[0][i];//第一个就是本身,初始化
		//本身的单词的个数,就是单词的本身 
		for(int j=0;j<i;j++)//枚举每一个单词的从头到尾 
			for(int k=2;k<=min(m,j+1);k++)//分割的数量之间最小分割 
			{
				f[i][k]=max(f[i][k],f[j][k-1]+sum[j+1][i]);
			}
	}
	cout<<f[len-1][m]<<endl;
}
int main()
{
	cin>>n>>m;//输入p k 
	//注意这里的m是分割的 
	for(int i=1;i<=n;i++)//输入n个字典字符串 
	{
		cin>>b;//输入字符串 
		a=a+b;//不需要开str数组,直接用加法,链接字符串
		//将所有单词拼接一起 
	}
	cin>>s;//字典的数量 
	len=a.length();//
	for(int i=1;i<=s;i++) cin>>ss[i];//查找单词
	for(int i=1;i<=s;i++) lenth[i]=ss[i].length(); //存储长度 
	work();
	solve(); 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值