UVA1401 Remember the Word
思路
首先有一个比较朴素的 DP 就是记
初始状态为
但是直接按这个方程转移的话需要枚举每一个
跟前缀有关的数据结构,不难想到字典树。把每一个
由于题目保证了
代码
有一个小技巧就是在单词结束的节点内保存这个单词的长度,不过直接在查询时累加长度当然也可行。
#include <bits/stdc++.h> using i64 = long long; constexpr int mod = 20071027; template<size_t SIZ = int(1e5)> struct Trie { std::vector<std::vector<int>> next; std::vector<int> f, end; Trie() { next.reserve(SIZ), next.emplace_back(26), end.push_back(0); } void insert(const std::string &s) { int p = 0; for (int i = 0; i < s.length(); i++) { int d = s[i] - 'a'; if (!next[p][d]) { next.emplace_back(26), end.push_back(0); next[p][d] = next.size() - 1; } p = next[p][d]; } end[p] = s.length(); } void find(const std::string &s, int st) { int p = 0; for (int i = st; i < s.length(); i++) { int d = s[i] - 'a'; if (!next[p][d]) { return; } p = next[p][d]; if (end[p]) { (f[st] += f[st + end[p]]) %= mod; } } } int solve(const std::string &s) { f.clear(), f.resize(s.length() + 1), f[s.length()] = 1; for (int i = s.length() - 1; ~i; i--) { find(s, i); } return f[0]; } }; void solve(int id, const std::string &s) { int n; std::cin >> n; Trie<> trie; for (int i = 0; i < n; i++) { std::string t; std::cin >> t; trie.insert(t); } std::cout << "Case " << id << ": " << trie.solve(s) << "\n"; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::string s; int cnt = 0; while (std::cin >> s) { solve(++cnt, s); } return 0; }
本文作者:forgot-dream
本文链接:https://www.cnblogs.com/forgot-dream/p/17472739.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步