[XSY] 相似(DP套DP)

相似

在看这道题前,有必要先看一下DP套DP的入门题[uoj3864]Hero meet devil,附上两篇写得不错的题解:
https://blog.csdn.net/Ike940067893/article/details/87863041
https://www.cnblogs.com/RabbitHu/p/BZOJ3864.html

  • 可以发现,SSSTTT相似,等价于它们的最长公共子序列长度至少为n−kn-knk
  • 考虑如何求两个字符串的LCS。设 lcsi,jlcs_{i,j}lcsi,j 表示 S[1...i]S[1...i]S[1...i]T[1...j]T[1...j]T[1...j] 的 LCS 长度,转移显然为
    lcsi,j={lcsi−1,j−1+1(S[i]==T[j])max{lcsi−1,j,lcsi,j−1}(S[i]!=T[j])lcs_{i,j}=\left\{ \begin{aligned} &lcs_{i-1,j-1}+1(S[i]==T[j]) \\ & max\{lcs_{i-1,j},lcs_{i,j-1}\} (S[i]!=T[j])\\ \end{aligned} \right. lcsi,j={lcsi1,j1+1(S[i]==T[j])max{lcsi1,j,lcsi,j1}(S[i]!=T[j])
  • 考虑如何拓展到TTT任意的情况。自然的想法是DP套DP:设dp[j][lcs1,j,lcs2,j,...,lcsn,j]dp[j][lcs_{1,j},lcs_{2,j},...,lcs_{n,j}]dp[j][lcs1,j,lcs2,j,...,lcsn,j]表示 考虑到TTT的前jjj位,lcs−,jlcs_{-,j}lcs,j的情况如第二维所示 的方案数
  • 直接这样维护状态肯定是行不通的,考虑优化:
    1.发现 lcsi,j−lcsi−1,j∈{0,1}lcs_{i,j}-lcs_{i-1,j}\in\{0,1\}lcsi,jlcsi1,j{0,1},那么 lcs1,j,lcs2,j,...,lcsn,jlcs_{1,j},lcs_{2,j},...,lcs_{n,j}lcs1,j,lcs2,j,...,lcsn,j的差分数组必是一个01 串 ,我们 状压这个01串 来描述第二维的状态
    2.nnn位01串还是太大了,考虑如何利用kkk很小这个性质进行优化
    考虑某个lcsi,j,若∣i−j∣>k,那么在转移到lcsn,n时,必然值不超过lcsi,j+min{n−i,n−j}<=min{i,j}+min{n−i,n−j}=n−∣i−j∣<n−k\color{Red}{考虑某个lcs_{i,j}},若|i-j|>k,那么在转移到lcs_{n,n}时,必然值不超过lcs_{i,j}+min\{n-i,n-j\}<=min\{i,j\}+min\{n-i,n-j\}=n-|i-j|<n-klcsi,jij>klcsn,nlcsi,j+min{ni,nj}<=min{i,j}+min{ni,nj}=nij<nk
    因此这样的lcsi,jlcs_{i,j}lcsi,j是没用的,可以直接丢掉,即对于每个jjj,我们只需要记录lcsj−k,j,lcsj−k+1,j,...,lcsj+k,jlcs_{j-k,j},lcs_{j-k+1,j},...,lcs_{j+k,j}lcsjk,j,lcsjk+1,j,...,lcsj+k,j
    3.只知道lcsj−k,jlcs_{j-k,j}lcsjk,j~lcsj+k,jlcs_{j+k,j}lcsj+k,j的差分数组,我们是无法知道它们的实际值的,因此考虑开多一维来记录lcsj,jlcs_{j,j}lcsj,j的实际值以推出其它的lcslcslcs值,即我们设dp[j][x][s]dp[j][x][s]dp[j][x][s]表示 考虑到TTT的前jjj位,lcsj,j==xlcs_{j,j}==xlcsj,j==xlcsj−k,j,lcsj−k+1,j,...,lcsj+k,jlcs_{j-k,j},lcs_{j-k+1,j},...,lcs_{j+k,j}lcsjk,j,lcsjk+1,j,...,lcsj+k,j的差分数组状压后为sss 的方案数
    4.∵lcsn,n∈[n−k,n](即不匹配的字符最多k个)\because lcs_{n,n}\in [n-k,n](即不匹配的字符最多k个)lcsn,n[nk,n](k)
    ∴∀j∈[1,n]满足lcsj,j∈[j−k,j]\therefore\forall j\in[1,n]满足lcs_{j,j}\in [j-k,j]j[1,n]lcsj,j[jk,j],所以我们可以将dpdpdp的第二维设置为lcsj,j−(j−k)=lcsj,j−j+klcs_{j,j}-(j-k)=lcs_{j,j}-j+klcsj,j(jk)=lcsj,jj+k,即dp[][x][]dp[][x][]dp[][x][]表示lcsj,j−j+k==xlcs_{j,j}-j+k==xlcsj,jj+k==x,这样就令x∈[0,k]x\in[0,k]x[0,k]
  • 考虑如何实现状态转移。dpdpdp数组的第三维不好直接得到,我们考虑把它预处理出来:设p[i][j][s1][c]p[i][j][s1][c]p[i][j][s1][c]表示考虑到TTT的前iii位,lcsi,i==jlcs_{i,i}==jlcsi,i==j(知道lcsi,ilcs_{i,i}lcsi,i就可以通过差分数组推出其它的lcslcslcs值),lcsi−k,i,lcsi−k+1,i,...,lcsi+k,ilcs_{i-k,i},lcs_{i-k+1,i},...,lcs_{i+k,i}lcsik,i,lcsik+1,i,...,lcsi+k,i的差分数组状压后为s1,在TTTi+1i+1i+1位新增字符ccc后,lcsi+1−k,i+1,lcsi+2−k,i+1,...,lcsi+1+k,i+1lcs_{i+1-k,i+1},lcs_{i+2-k,i+1},...,lcs_{i+1+k,i+1}lcsi+1k,i+1,lcsi+2k,i+1,...,lcsi+1+k,i+1状压完的差分数组
  • 同样,需要优化ppp的状态设置:
    1.同上,我们可以将ppp的第二维设置为lcsi,i−(i−k)=lcsi,i−i+klcs_{i,i}-(i-k)=lcs_{i,i}-i+klcsi,i(ik)=lcsi,ii+k,即p[][j][][]p[][j][][]p[][j][][]表示lcsi,i−i+k==jlcs_{i,i}-i+k==jlcsi,ii+k==j,这样就令j∈[0,k]j\in[0,k]j[0,k]
    2.其实ppp转移到的新差分数组状态与新增字符具体是什么无关,与新增字符与S每一位的匹配情况有关。再进一步地,
    ∵lcsh,h∈[h−k,h]\because lcs_{h,h}\in [h-k,h]lcsh,h[hk,h]
    ∴T[h]只可能与S[h−k]\therefore T[h]只可能与 S[h-k]T[h]S[hk]~S[h+k]匹配S[h+k] 匹配S[h+k],即我们只需要考虑新增字符与S[i+1−k]S[i+1-k]S[i+1k]~S[i+1+k]S[i+1+k]S[i+1+k]的匹配情况。直接把第四维设置成这个匹配情况即可。
    3.仔细想想,把第四维改成匹配情况后,ppp的转移已经与第一维无关了,直接删掉即可

至此,这道题就可以实现了

#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 998244353
using namespace std;
typedef pair<int,int> pr;
const int N=30001;
const int K=5;
const int S=256;
int n,m,ans,dp[N][K][S],f[31],g[31];
pr p[K][S][S<<1];
char ch[N];
bool flag[31];
int add(int a,int b){a=a+b;if(a>mod) a-=mod;return a;
} 
int mul(int a,int b){return 1ll*a*b%mod;
}
void dfs(int a,int b,int c){if(dp[a][b][c]==0) return;int l=max(a-m,0),r=min(a+m,n-1),sz=26;for(int i=l;i<=r;i++){if(!flag[ch[i+1]-'A']){flag[ch[i+1]-'A']=1;sz--;}f[ch[i+1]-'A']|=(1<<(i-a+m));//统计每种字符的匹配情况 }for(int i=l;i<=r;i++){if(flag[ch[i+1]-'A']){int x=p[b][c][f[ch[i+1]-'A']].first;int y=p[b][c][f[ch[i+1]-'A']].second;if(x>=0) dp[a+1][x][y]=add(dp[a+1][x][y],dp[a][b][c]);flag[ch[i+1]-'A']=0;f[ch[i+1]-'A']=0;}}int x=p[b][c][0].first,y=p[b][c][0].second;if(x>=0) dp[a+1][x][y]=add(dp[a+1][x][y],mul(dp[a][b][c],sz));
}
int main(){scanf("%s%d",ch+1,&m);n=strlen(ch+1);//省略一维l,表示考虑到第l位 for(int i=0;i<=m;i++){//lcs[l][l]-l+m==i for(int j=0;j<(1<<(2*m));j++){//lcs[l-m][l]~lcs[l+m][l]的差分数组状压 for(int k=0;k<(1<<(2*m+1));k++){//T[l+1]与S[l+1-m]~S[l+1+m]匹配情况状压 //f:(lcs[l-m][l]-l+m)~(lcs[l+m][l]-l+m) //g:(lcs[l+1-m][l+1]-l+m)~(lcs[l+1+m][l+1]-l+m)f[m]=i;for(int a=m-1;a>=0;a--) f[a]=f[a+1]-(j>>a&1);for(int a=m;a<2*m;a++) f[a+1]=f[a]+(j>>a&1);for(int a=0;a<=2*m;a++){if((k>>a)&1) g[a+1]=max(f[a]+1,f[a+1]);//匹配else g[a+1]=max(f[a],f[a+1]); //不匹配 g[a+1]=max(g[a],g[a+1]);}int x=g[m+1]-1;//x=lcs[l+1][l+1]-(l+1)+mint y=0;if(x>=0){for(int a=m-1;a>=0;a--) if(g[a+1]^g[a+2]) y|=1<<a;for(int a=m;a<2*m;a++) if(g[a+1]^g[a+2]) y|=1<<a;}p[i][j][k]=make_pair(x,y);}}}//预处理 for(int i=0;i<=30;i++) f[i]=0;dp[0][m][0]=1;for(int i=0;i<n;i++){//考虑到第i位 for(int j=0;j<=m;j++){//lcs[i][i]-i+m==j for(int k=0;k<(1<<(2*m));k++){//差分数组状压 dfs(i,j,k);}}}//dpfor(int i=0;i<=m;i++){for(int j=0;j<(1<<(2*m));j++){ans=add(ans,dp[n][i][j]);}}printf("%d\n",ans);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/320216.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P3295-[SCOI2016]萌萌哒【ST表,并查集】

正题 题目链接:https://www.luogu.com.cn/problem/P3295 题目大意 一个nnn位的数字&#xff0c;mmm个条件给出两个完全相同的区间&#xff0c;求可能的数字数量。 解题思路 其实就是区间中的每个数字分别连边&#xff0c;但是这样显然会TTT。考虑通过消耗查询的复杂度来平衡…

牛客IOI周赛16-普及组

比赛链接 文章目录求导题目描述题解&#xff1a;猜数题意&#xff1a;题解&#xff1a;方法一 贪心方法二 暴力答题卡题意&#xff1a;题解&#xff1a;代码&#xff1a;求导 链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C …

【归并排序】休息(jzoj 3462)

休息 jzoj 3462 题目大意 给你一个序列&#xff0c;你每一回合把它划分成尽可能少的单调递减的序列&#xff08;第一次划分到的序列长度都是偶数&#xff09;&#xff0c;然后把每个序列翻转&#xff0c;问你把它变成单调递增的序列要翻转多少次 输入样例 6 5 3 2 1 6 4输…

Pipelines - .NET中的新IO API指引(二)

原文&#xff1a;Pipelines - a guided tour of the new IO API in .NET, part 2作者&#xff1a;marcgravell在上一章&#xff0c;我们讨论了以往的StreamAPI中存在的一些问题&#xff0c;并且介绍了Pipe,PipeWriter,PipeReader 等API&#xff0c;研究如何写出一个Pipe 并且从…

[XSY] 线图(树形DP、分类讨论)

线图 如图&#xff0c;每个L(L(T))上的点对应T上的一条三点链 在连接L(L(T))上两点&#xff0c;当且仅当两点代表的三点链在T上有共边&#xff0c;且边权为 共边边权*2非共边1边权非共边2边权 在L(L(T))上从点u走到点v&#xff0c;等价于u代表的三点链在T上删掉自己的一条边&…

Bzoj3309-DZY Loves Math【莫比乌斯反演,线性筛】

正题 bzoj没了&#xff0c;在darkbzoj交吧 题目链接:https://darkbzoj.tk/problem/3309 题目大意 定义f(x)f(x)f(x)表示xxx所有质因数中最大的指数幂。 求∑i1n∑j1mf(gcd(i,j))\sum_{i1}^n\sum_{j1}^mf(\ gcd(i,j)\ )i1∑n​j1∑m​f( gcd(i,j) ) 解题思路 很显然要用莫反…

牛客网【每日一题】4月29日题目精讲 Symmetric Matrix

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 524288K&#xff0c;其他语言1048576K 64bit IO Format: %lld题目描述 输入描述: The input consists of several test cases and is terminated by end-of-file. Each test c…

邻接矩阵和邻接表的使用

邻接矩阵和邻接表的使用 邻接矩阵 为了遍历一个图&#xff0c;我们使用了邻接矩阵&#xff0c;及用ai,ja_{i,j}ai,j​表示由a到b的边权 注&#xff1a;若这两个点不相连或ijijij&#xff0c;那么这个值就会设定为一个非正常的值&#xff0c;以便遍历时特判不走这条边 使用&am…

YbtOJ#20239-[冲刺NOIP2020模拟赛Day10]连边方案【状压dp】

正题 题目链接:https://www.ybtoj.com.cn/contest/68/problem/3 题目大意 求有多少个nnn个点mmm条边的无向图满足 有连边的点之间编号差不超过kkk所有点的度数都为偶数 解题思路 因为kkk很小&#xff0c;所以我们考虑状压一个点前kkk个点的奇偶状态。设fi,j,s,0/1f_{i,j,s,…

有上下界网络流问题汇总

无源汇有上下界可行流 法一&#xff08;据说适合点少边多的图&#xff09;&#xff1a; 建图方法 首先建立附加源点ss和附加汇点tt对于原图中的边x->y&#xff0c;若限制为[b,c]&#xff0c;那么连边x->y&#xff0c;流量为c-b对于原图中的某一个点i&#xff0c;记d(i…

一个迄今为止最快的并发键值存储库FASTER诞生

FASTER在过去十年中&#xff0c;云中的数据密集型应用程序和服务有了巨大的增长。数据在各种边设施&#xff08;例如&#xff0c;设备&#xff0c;浏览器和服务器&#xff09;上创建&#xff0c;并由云应用程序处理用来获得数据价值或做出决策。应用程序和服务可以处理收集的数…

【斜率优化】仓库建设(luogu 2120)

仓库建设 luogu 2120 题目大意 有一个斜坡&#xff0c;上面有n个工厂&#xff08;山顶是1&#xff0c;山脚是nnn&#xff0c;工厂都是漏填&#xff09;&#xff0c;上面有pip_ipi​个货物&#xff0c;和工厂1的距离为x1x_1x1​ 现在有一场大雨&#xff0c;你可以在某些工厂处…

牛客网【每日一题】4月30日题目精讲 换个角度思考

链接&#xff1a; 文章目录题目描述题解&#xff1a;主席树做法&#xff1a;代码&#xff1a;树状数组&#xff1a;更扯淡的方法&#xff01;&#xff01;&#xff01;时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言…

三元环计数四元环计数

三元环计数 问题 给出一张n个点m条边的无向图&#xff0c;问图中有多少个三元组{ u , v , w } &#xff0c;满足图中存在 { (u,v) , (v,w) , (w,u) } 三条边。 求解 Step1 定向 将所有点按 度数 从小到大排序&#xff0c;如果度数相同按 点编号 从小到大排序&#xff0c;u…

YbtOJ#20240-[冲刺NOIP2020模拟赛Day10]弱者对决【笛卡尔树,区间dp】

正题 题目链接:https://www.ybtoj.com.cn/contest/68/problem/4 题目大意 mmm个三元组(ai,bi,ci)(a_i,b_i,c_i)(ai​,bi​,ci​)&#xff0c;如果ci≥min{xj}(ai≤j≤bi)c_i\geq min\{x_j\}(a_i\leq j\leq b_i)ci​≥min{xj​}(ai​≤j≤bi​)那么可以获得min{xj}min\{x_j\}mi…

牛客网【每日一题】5月1日题目 [SCOI2012]滑雪与时间胶囊

链接&#xff1a; 时间限制&#xff1a;C/C 2秒&#xff0c;其他语言4秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 a180285非常喜欢滑雪。他来到一座雪山&#xff0c;这里分布着M条供滑行的轨道和N个轨道之间的交点&#x…

漫谈单体架构与微服务架构(上):单体架构

最近微服务架构特别火爆&#xff0c;就跟人工智能、区块链一样&#xff0c;软件架构设计如果不提微服务&#xff0c;感觉就像是与世界先进的架构风格和开发技术脱了节似的&#xff0c;各方各面都无法彰显高大上的气质。本来再打算使用一套系列文章来讨论微服务的方方面面&#…

【数学】奶牛编号(jzoj 2932)

奶牛编号 jozj 2932 题目大意 求出有m个1的01串中字典序第n大的字典序 输入样例 7 3输出样例 10110数据范围 1⩽M⩽101 \leqslant M \leqslant 101⩽M⩽10 1⩽N⩽1071 \leqslant N \leqslant 10^71⩽N⩽107 解题思路 我们先从01串长度入手&#xff1a; 先对m1m 1m1的特…

CF732F Tourist Reform(dfs树、边双连通图、tarjan)

因为知道了算法tag&#xff0c;所以想到了正解&#xff1a; 先给出两个性质&#xff1a; 边双给边定向一定可以转为强连通图,此为最优解树给边定向后R的最小值必为0 性质2证明如下&#xff1a; 设树有n个节点, 若R_min!0, 则每点出度至少为1,各点出度之和至少为n, 则至少有…

【归并排序】奶牛的图片(jzoj 1812)

奶牛的图片 jzoj 1812 题目大意 给你一个序列&#xff0c;你可以交换相邻的两个数 让你用最少的交换次数来使得这个序列变成形如a1,a2...n,1,2...a−1,aa1,a2...n,1,2...a-1,aa1,a2...n,1,2...a−1,a的序列 问你最少的交换次数是多少次 输入样例 5 3 5 4 2 1输出样例 2解…