洛谷PP2031 脑力达人之分割字串【字符串DP】【黄】

该博客探讨了一道关于字符串分割的问题,其中涉及到动态规划和C++编程。博主首先介绍了问题背景,即如何根据给定的字典将字符串分割成最多包含字典中单词的子串,并提供了数据范围和输入输出样例。博主分享了两种解题思路,重点解释了状态转移方程,并指出了第一种方法的遗漏。尽管第一种尝试未能通过所有测试用例,但第二种思路修正了这个问题,实现了正确解法。

Date:2022.03.16
题目描述
现在有一个字符串,你可以对这个字符串进行拆分,如 abcvsdaas 可以拆分为 abc|vs|d|aas,现在再给你一个字典,要求分割成的每一个子串必须要有包含其中的任意一个单词。那么最多可以分为几个子串呢?
输入格式
第一行,一行字符串
第二行一个正整数 N,表示字典中字符串的数量
接下来 N 行,每行一个字符串 Ai,表示字典中的一个字符串。
输出格式
一个整数,表示最多的分割数。
输入输出样例
输入 #1复制
asdsd
3
as
sd
ds
输出 #1复制
2
说明/提示
特殊情况:
如果原字符串不能被分割,请输出 0。
数据范围:
对于 20% 的数据,1≤∣s∣≤50,1≤n≤50。
对于 100% 的数据,1≤∣Ai∣≤∣s∣≤300,1≤N≤500。
其中,|s|,|Ai| 表示字符串 s 与 Ai 的长度。

思路①:问题即求出给定串最多包含几个子串,子串是可重复的(例:abab是两个ab),但不可交叉(例:abs,其中不能认定为含ab和bs两个子串)。
f[i]:f[i]:f[i]:iii为结尾的串最多可分出几个子串。
设第jjj个子串为zc[j]zc[j]zc[j]状态转移方程:f[i]=max(f[i],f[i−zc[j].length()]+1)f[i]=max(f[i],f[i-zc[j].length()]+1)f[i]=max(f[i],f[izc[j].length()]+1)
【zc[j]==s.substr(i−zc[j].length()+1,i)∧i>=zc[j].length()】【zc[j]==s.substr(i-zc[j].length()+1,i) \wedge i>=zc[j].length()】zc[j]==s.substr(izc[

### 如何在C++中使用特定字符分割字符串的方法 在C++中,可以使用标准库中的`std::string`类和`std::stringstream`来实现字符串分割。此外,还可以使用`strtok`函数(如引用[^1]所示),或者自定义函数来完成这一任务。 以下是一个使用`std::stringstream`和`std::getline`方法分割字符串的示例代码: ```cpp #include <iostream> #include <sstream> #include <vector> #include <string> std::vector<std::string> split(const std::string& str, char delimiter) { std::vector<std::string> tokens; std::stringstream ss(str); std::string token; while (std::getline(ss, token, delimiter)) { tokens.push_back(token); } return tokens; } int main() { std::string str = "This,is,a,test,string"; char delimiter = ','; std::vector<std::string> result = split(str, delimiter); for (const auto& s : result) { std::cout << s << std::endl; } return 0; } ``` 上述代码定义了一个`split`函数,该函数接受一个字符串和一个分隔符作为参数,并返回一个包含分割后子字符串的向量。通过`std::stringstream`和`std::getline`,可以方便地按照指定的字符对字符串进行分割[^2]。 另一种方法是使用`strtok`函数,如引用[^1]中所示。以下是使用`strtok`的示例代码: ```cpp #include <iostream> #include <cstring> #include <string> int main() { std::string str = "Please split this sentence into tokens"; char* cstr = new char[str.length() + 1]; std::strcpy(cstr, str.c_str()); char* token = std::strtok(cstr, " "); while (token != nullptr) { std::cout << token << std::endl; token = std::strtok(nullptr, " "); } delete[] cstr; return 0; } ``` `strtok`函数会修改原始字符串,因此需要先将`std::string`转换为C风格字符串,并分配足够的内存空间。每次调用`strtok`时,第一个参数为`nullptr`,以继续从上次分割的位置开始[^1]。 此外,还可以使用第三方库如Boost中的`boost::split`函数来简化字符串分割操作。例如: ```cpp #include <iostream> #include <vector> #include <string> #include <boost/algorithm/string.hpp> int main() { std::string str = "This-is-a-test-string"; std::vector<std::string> result; boost::split(result, str, [](char c) { return c == '-'; }); for (const auto& s : result) { std::cout << s << std::endl; } return 0; } ``` 此方法利用了Boost库中的`boost::split`函数,支持更灵活的分割逻辑[^3]。 ### 注意事项 - 使用`strtok`时需要注意线程安全性问题,因为它会修改原始字符串并维护内部状态。 - 如果需要处理复杂的分隔符规则,建议使用`std::stringstream`或第三方库。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值