题目背景:
分析:又是一道trie + , 这道题是trie + DP,直接针对每一位处理如果从这一位截断,那么形成的单词是什么,具体详见代码
Source:
#include
#include
#include
#include
#include
#include
#include
using namespace std; int n, tot, m; int dp[100010]; string str, s[100010], s1[100010]; struct TRIE { int son[26]; int num; } trie[1000010]; void build_trie(string &s, int num) { int len = s.size(); for (int i = 0; i < len; ++i) if (s[i] >= 'A' && s[i] <= 'Z') s[i] = s[i] - 'A' + 'a'; int position = 0; for (int i = 0; i < len; ++i) { if (!trie[position].son[s[i] - 'a']) trie[position].son[s[i] - 'a'] = ++tot; position = trie[position].son[s[i] - 'a']; } trie[position].num = num; } void dfs(int pos) { if (pos < 0) return ; dfs(pos - s[dp[pos]].size()); cout << s1[dp[pos]] << " "; } int main() { cin >> n >> str >> m; for (int i = 1; i <= m; ++i) cin >> s[i], s1[i] = s[i], build_trie(s[i], i); int position; for (int i = 0; i < n; ++i) { /*对每一位处理,以当前为一个断点是否可以有单词, 若可以,则保存dp[i]为当前单词编号*/ int position = 0; for (int j = i; j >= 0; --j) { if (!trie[position].son[str[j] - 'a']) break; position = trie[position].son[str[j] - 'a']; if (trie[position].num && (i - (i - j + 1) < 0 || dp[i - (i - j + 1)])) { /*判断当前为开头,或者是上一个位置有可行解*/ dp[i] = trie[position].num; break; } } } int pos = n - 1; dfs(n - 1); /*从前往后输出,递归回溯*/ return 0; }