题目链接:https://codeforces.com/contest/1303
E - Erase Subsequences
题意:从一个长度为 \(n(1\leq n \leq 400)\) 的字符串 \(s\) 中,进行至多两次操作,问是否能构造出长度为 \(m(1\leq m\leq 400)\) 的字符串 \(t\) 。每次操作,从字符串 \(s\) 中取出一个子序列,接在当前字符串 \(p\) 的后面,初始时, \(p\) 为空串。同一个字符不能被取出2次。
题解:一开始搞了个贪心,结果连第一个样例都过不了,其实看复杂度就知道过不了了。看一下性质(无后效性)其实很容易想到一种 \(dp\) 的算法,但是只想到一个 \(O(n^4)\) 的dp,先枚举字符串 \(t\) 的前半部分和后半部分的分界线,然后用一个 \(dp[i][j][k]\) 表示字符串 \(s\) 的前 \(i\) 个字符是否可以匹配前半的字符串 \(t\) 的前 \(j\) 个字符以及字符串 \(t\) 的后半的前 \(k\) 个字符。这个算法不高效的原因很可能是因为lyd说的“没有把状态压缩到极致”,很明显每个 \(dp\) 只是布尔值的话可以用一些什么bitset优化。别人的正解其实多压缩了一维,也改变了实际上设计的状态,用 \(dp[i][j]\) 表示字符串 \(s\) 的前 \(i\) 个字符匹配字符串 \(t\) 的前半的前 \(j\) 个字符时,最多匹配字符串 \(t\) 的后半的前多少个字符。进行这样的状态压缩,实际上基于一种贪心,因为匹配 \(k\) 个字符可行,那么匹配少于 \(k\) 个字符显然都是可行的。
来源:https://www.cnblogs.com/KisekiPurin2019/p/12302160.html