【扩展KMP】【树状数组优化dp】字符串游戏
来源:互联网 发布:python 捕获ctrl c 编辑:程序博客网 时间:2024/06/07 05:11
tsy:衣服串你会啥? me:会乱搞!
这题。。我记得当时写了个。。。搜索。。。各种MLE掉了………… = =
正解呢 是扩展KMP+树状数组优化dp。。
先来说扩展KMP怎么写。。。这道题只用对自己跑扩展KMP 所以就只用写一个函数就行了
inline void e_kmp(){int j = 0, last = 1;for(; j < len && s[j] == s[j + 1]; ++j);p[0] = len; p[1] = j;for(int i = 2; i < len; ++i){int itmax = p[i - last], already = max(0, last + p[last] - i);if(itmax < already) p[i] = itmax;else {p[i] = already; last = i;while(i + p[i] < len && s[i + p[i]] == s[p[i]]) ++p[i];}}}
数组p[i]表示 s[0...j] == s[i...k] 的j的最大值 首先初始化 p[0] 和 p[1] 然后从 p[2] 开始推。。
画个比较丑的图以防我以后忘掉了。。相同颜色的区间表示这两个字串完全相同。。。
last表示( last + p[last] )最大的那个位置 也就是说最远已经匹配到哪里了
然后我们现在要匹配的是i。。假如 itmax < already 那么 i-last可以匹配多少(值就是itmax) i就可以匹配多少 (因为already段是相同的)
如果 itmax >= already 至少可以证明 [i...i+already] 是一定匹配的 那么就从这个地方开始继续尝试匹配
同时可以看出 如果 itmax > already 那么i就会匹配得比之前的last还远 那么i就变成last。。
然后就是dp了。。设 dp[i] 表示把一个空串变成 A[1...i] 需要的最小费用 那么 dp[i] 初值即为 i * x
考虑怎么更新 对于位置 i * 2 如果 p[i] >= i 那么就可以直接复制一遍这个串 dp[i * 2] = min(dp[i * 2], dp[i] + y)
对于位置 [i+1, i+p[i]] 从i转移是既需要剪裁又需要复制的 令这个位置为k dp[k] = min(dp[k], dp[i] + y + z)
直接转移是n^2的 我们发现可以用线段树优化 每次更新[i + 1, i + p[i]]
然后维护区间最值也是可以用树状数组的(网上偷了份代码T_T)
void Init(int n){ for(int i=1;i<=n;i++){ idx[i]=num[i]; for(int j=1;j<Lowbit(i);j<<=1){ idx[i]=MAX(idx[i],idx[i-j]); } }}int Query(int l,int r){ int ans=num[r]; while(true){ ans=MAX(ans,num[r]); if(r==l) break; for(r-=1;r-l>=Lowbit(r);r-=Lowbit(r)){ ans=MAX(ans,idx[r]); } } return ans;}void Modify(int p,int v,int n){ num[p]=v; for(int i=p;i<=n;i+=Lowbit(i)){ idx[i]=v; for(int j=1;j<Lowbit(i);j<<=1){ idx[i]=MAX(idx[i],idx[i-j]); } }}
但是这题没那么麻烦。。因为对于任何的i 一定是更新 [i+1, x] 由于是从前往后更新 [1, i] 这个区间的值不会再被用到 所以可以直接更新 [1, x]
然后这题。。。就没了。。。
#include <cstdio>#include <iostream>#include <cstring>using namespace std;const int Nmax = 2 * 1e5 + 5; char s[Nmax];int len, p[Nmax], dp[Nmax];int x, y, z;namespace BIT{int mmin[Nmax];inline void init(){ memset(mmin, 0x3f, sizeof(mmin)); }inline int lowbit(int x){ return x & (-x); }void update(int idx, int w){for(int i = idx; i; i -= lowbit(i)) mmin[i] = min(mmin[i], w);}int query(int idx){int res = 0x3f3f3f3f;for(int i = idx; i <= len; i += lowbit(i))res = min(res, mmin[i]);return res;}}inline void e_kmp(){int j = 0, last = 1;for(; j < len && s[j] == s[j + 1]; ++j);p[0] = len; p[1] = j;for(int i = 2; i < len; ++i){int itmax = p[i - last], already = max(0, last + p[last] - i);if(itmax < already) p[i] = itmax;else {p[i] = already; last = i;while(i + p[i] < len && s[i + p[i]] == s[p[i]]) ++p[i];}}}int main(){freopen("catstring.in", "r", stdin);freopen("catstring.out", "w", stdout);ios::sync_with_stdio(false);cin >> s >> x >> y >> z;len = strlen(s); e_kmp();for(int i = 1; i <= len; ++i) dp[i] = i * x;using namespace BIT; init();for(int i = 1; i <= len; ++i){dp[i] = min(dp[i], query(i));int x = min( len, min((i << 1) - 1, i + p[i]) );update(x, dp[i] + y + z);if(p[i] >= i) dp[i << 1] = min(dp[i << 1], dp[i] + y);}printf("%d\n", dp[len]);return 0;}
- 【扩展KMP】【树状数组优化dp】字符串游戏
- 【HDU4991】dp 树状数组优化
- hdu5542 树状数组优化dp
- BZOJ3594 树状数组优化DP
- BZOJ_P1461 字符串的匹配(KMP+树状数组)
- HDU - 4991(树状数组优化 dp)
- hdu 3450 树状数组优化dp
- bzoj4361 isn(树状数组优化DP)
- [dp+树状数组优化] CF597C. Subsequences
- hdu 5542(树状数组优化dp)
- hdu 3450(树状数组优化dp)
- hdu 2227(树状数组优化dp)
- hdu 4991(树状数组优化dp)
- Codeforce 597C(dp+树状数组优化)
- ZCMU 1708 树状数组优化dp
- HNOI2012 双十字 DP+树状数组优化
- HDU 5542 (DP+树状数组优化)
- #HDU3450#Counting Sequences(Dp+树状数组优化)
- 数据库范式
- 黑马程序员——Java的内存世界:面向对象的概念以及对象的建立过程
- -server 'default' is an unknown server in the configuration file.
- LeetCode OJ Reverse Bits
- 第三周项目1-三角形类(一)
- 【扩展KMP】【树状数组优化dp】字符串游戏
- 多线程中递归锁的实现
- 信号量、互斥体和自旋锁
- Asp.net 2.0 C#实现压缩/解压功能
- A/B的困扰
- jquery验证
- [数据结构复习]树_二叉树
- 不允许创建临时变量,交换两个数的内容
- Enum使用心得