【题解】SDOI2021集训 R1 半夜

image
image

先贴两个博客:ajthreac yspm,建议结合起来看

\(O(n^3)\):对 \(XX\) 每个长度为 \(n\) 的字串与 \(Y\) 跑 LCS。设 \(f[i,j,k]\) 表示 \(X[i..j],Y[1..k]\) 的 LCS,暴力转移:\(f[i,j,k]=\max(f[i,j-1,k],f[i,j,k-1],[X[j]=Y[i]](f[i,j-1,k-1]+1))\)

考虑两个性质:

\[f[i-1,j,k]>f[i-1,j-1,k]\Rightarrow f[i,j,k]>f[i,j-1,k] \]

\[f[i-1,j,k-1]>f[i-1,j,k-1]\Rightarrow f[i,j,k]>f[i,j,k-1] \]

证明没看懂,这里提供感性理解:
\(f[i-1,j,k]>f[i-1,j-1,k]\) 说明 \(X[j]\) 可以与 \(Y\) 中一个元素匹配,那么移动 \(i\) 对其他部分的影响相同,且不会影响它,那么 \(f[i,j,k]\)\(>f[i,j-1,k]\),第二个同理。

通过这两个性质可以发现一定存在分割点 \(p[j,k],q[j,k]\) 使 \(f[i,j,k]=f[i,j-1,k]+[i>p[j,k]]=f[i,j,k-1]+[i<q[j,k]]\),用 \(p[j,n]\) 就能 \(O(n^2)\) 递推出 \(f[i,i+n-1,n]\)
注意这里 \(p,q\) 的两维与上两篇是反的,边界也不太相同。

考虑如何求 \(p,q\)
\(F=f[i,j-1,k-1],P=p[j-1,k],Q=q[j,k-1]\)。分类讨论:

  • \(X[j]\neq Y[k]\)
    • \(P<Q\)
\(i\) \(P\) \(Q\)
\(f[i,j-1,k]\) \(F+1\) \(F+1\) \(F\)
\(f[i,j,k-1]\) \(F\) \(F+1\) \(F+1\)
\(f[i,j,k]\) \(F+1\) \(F+1\) \(F+1\)

其中 \(f[i,j,k]\) 的取值是根据最开始的暴力 DP 转移得到的,根据 \(f[i,j,k]\) 的取值就能得出 \(p[j,k]=Q,q[j,k]=P\)

其余三类也可以写出类似的表格,注意 \(X[j]=Y[k]\)\(f[i,j,k]=f[i,j-1,k-1]+1\),这里就不一一列出了。

代码异常简洁:

const int N = 4e3+5;
int n;
char a[N],b[N];

int m,ans,p[N][N],q[N][N];

signed main() {
	scanf("%d%s%s",&n,a+1,b+1); m = n+n; memcpy(a+n+1,a+1,n);
	For(j,1,m) p[j][0] = j;
	For(j,1,m) For(k,1,n) {
		int P = p[j][k-1], Q = q[j-1][k];
		if( a[j] != b[k] && P > Q ) p[j][k] = P, q[j][k] = Q;
		else p[j][k] = Q, q[j][k] = P;
	}
	For(i,1,n) {
		int now = 0;
		For(j,i,i+n-1) now += i>p[j][n];
		ckmax(ans,now);
	}
	write(ans);
	return iocl();
}
posted @ 2021-08-17 21:14  401rk8  阅读(85)  评论(1编辑  收藏  举报