「山东省队集训2021 Round 1」 半夜

考虑将 X 复制一次放到后面再对其长度为 n 的连续子串和 Y 求一波 Longest Common Subsequence 就能得到 Θ(n3) 的分数了

那么设 fi,j,k 表示 X[ij],Y[1k]LCS

考虑如下两个性质:

fi1,j,k>fi1,j1,kfi,j,k>fi,j1,k

fi,j,k>fi,j,k1fi1,j,k>fi1,j,k1

下文受篇幅限制只证明第一个:

因为这个 DP 类似于网格图上最大带权游走,那么设两个串的左端点为网格图起始点,右端点为终止点

不难发现两条路径必然存在交点,设 (i1,0)(j,k)最靠左 路径为 C1,而 (i,0)(j1,k) 的最靠左的最优路径为 C2

设两个路径公共部分是 C,之前是 C1A,C2A,之后的是 C1B,C2B,把已知和结论统统表示出来互相推就行了

那么必然存在 p(j,k),q(j,k) 满足:

f(i,j,k)=f(i,j1,k)+[ip(k,j)]=f(i,j,k1)+[i<q(k,j)]

至此可以得到所有 p(n,x) 然后使用第一个等号后的式子递推 f(x,x+n1,n) 即可

考虑如何转移 p,q

P=pk1,j,Q=qk,j1(认真注意变量定义)

  • XiYj

    如果 P<Q,把 fi,j1,k,fi,j,k1 的转移结果写出来就能发现 p(k,j)=Q,q(k,j)=P,因为 fi,j,kmax{fi,j1,k,fi,j,k1}

    而对于 PQ 的情况,仍然是写出来转移的结果得到 pi,j=P,q(i,j)=Q

  • Xi=Yj

    这里必然会有 fi,j,k=fi,j1,k1+1,那么分开讨论究竟是哪边加了 1,对转移有贡献的如下:

    如果 fi,j,k=fi,j1,k+1,即上次不能转移,但是现在可以,那么必然满足 iQ,p(k,j)=Q

    如果 fi,j,k=fi,j,k1,即提前转移过了,现在不能转移,那么必然满足 iP,q(k,j)=p

这样就可以了! 时间复杂度 O(n2)

Talk is cheap,Show the Code
const int N=2010;
int p[N][N<<1],q[N][N<<1],f[N<<1][N<<1],n,ans;
char x[N<<1],y[N];
signed main(){
	n=read(); scanf("%s%s",x+1,y+1); rep(i,1,n) x[i+n]=x[i];
	rep(i,1,n*2) p[0][i]=i+1; rep(i,1,n*2) q[0][i]=1;
	rep(i,1,n) rep(j,1,(n<<1)){
		int P=p[i-1][j],Q=q[i][j-1];
		if(P>=Q&&x[j]!=y[i]) p[i][j]=P,q[i][j]=Q;
		else p[i][j]=Q,q[i][j]=P;
	}
	rep(i,0,(n<<1)) rep(j,i,(n<<1)) f[i][j]=f[i][j-1]+(i>=p[n][j]);
	rep(i,1,n) ckmax(ans,f[i][i+n-1]); print(ans); return 0;
}
//Use The Time To Enrich This Selfclosing Youth
posted @   没学完四大礼包不改名  阅读(228)  评论(1编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示