NC16696 [NOIP2001]统计单词个数
题目
题目描述
给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份( 1 < k ≤ 40 ),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。
单词在给出的一个不超过6个单词的字典中。
要求输出最大的个数。
输入描述
每组的第一行有2个正整数(p,k)
p表示字串的行数,k表示分为k个部分。
接下来的p行,每行均有20个字符。
再接下来有1个正整数s,表示字典中单词个数。(1 ≤ s ≤ 6 )
接下来的s行,每行均有1个单词。
输出描述
1个整数,分别对应每组测试数据的相应结果。
示例1
输入
1 3 thisisabookyouareaoh 4 is a ok sab
输出
7
题解
知识点:枚举,线性dp,字符串。
这道题是 串最大和的变形,加和部分变为了字符串最多匹配的数量。
因此先预处理出 表示为区间 的最大匹配数。实现上需要逆推,因为要求是第一个字符不一样的匹配才算,所以逆推一个字符后看从这个字符出发有没有匹配的,有就加一。
设 为考虑到 个字符,共有 串。转移方程为:
表示不选从 出发的串,选 作为第 串。
由于不能选空串,因此初始化负无穷,并把初态 赋值 。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; int sum[207][207], dp[207][47]; string dir[10]; int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int p, k; cin >> p >> k; string str; while (p--) { string tmp; cin >> tmp; str += tmp; } int n = str.length(); str = '?' + str; int s; cin >> s; for (int i = 1;i <= s;i++) cin >> dir[i]; for (int j = n;j >= 1;j--) { for (int i = j;i >= 1;i--) { sum[i][j] = sum[i + 1][j]; bool ok = false; string tmp = str.substr(i, j - i + 1); for (int k = 1;k <= s;k++) ok |= tmp.find(dir[k]) == 0; sum[i][j] += ok; } } memset(dp, -0x3f, sizeof(dp)); for (int i = 0;i <= n;i++) dp[i][0] = 0; for (int i = 1;i <= n;i++) { for (int j = 1;j <= k;j++) { dp[i][j] = dp[i - 1][j]; for (int u = 0;u < i;u++) dp[i][j] = max(dp[i][j], dp[u][j - 1] + sum[u + 1][i]); } } cout << dp[n][k] << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16578784.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧