ABC185E. Sequence Matching
到现在 AK 一场 ABC 还要一个多小时,我果然是一点都不行
Statement
给定一个长度为 \(N\) 的序列 \(A\) 和一个长度为 \(M\) 的序列 \(B\)。
\(\text{Takahashi}\) 在 \(A\) 中删除了一些元素得到了序列 \(A ^ \prime\)。
同样,他在 \(B\) 中删除了一些元素得到了 \(B ^ \prime\)。
他得到的 \(A ^ \prime, B ^ \prime\) 满足 \(|A ^ \prime| = |B ^ \prime|\) (\(|s|\) 表示 \(s\) 的长度)
记他在 \(A, B\) 中删除的元素总数量为 \(x\),\(1 \leq i \leq |A ^ \prime|\) 且 \(A ^ \prime _ i \neq B ^ \prime _ i\) 的 \(i\) 的个数为 \(y\)。
最小化 \(x + y\)。
Solution
怎么都是自己推的 DP 式子啊……我来个模板的。
把整个过程看成 \(A\) 到 \(B\) 的转化。
-
对于删除总量,由于最后两个串长度相等,可以看成是往里加一个元素或者删去一个元素(加一个元素肯定是加另一个串中已有的一个元素,相当于是在另一个里面把这个删去)
-
对于不同的个数,可以看成是把一个修改成和另一个一样。
那么题目所求就是:删除、增加、编辑(修改) 的总量,也就是字符串编辑距离,经典问题。
Code
一开始想到编辑距离了但感觉是错的……然后敲了一个错的最长公共子序列,最后又想到这个建模……
//Author: RingweEH
const int N=1e3+10;
int n,m,a[N],b[N],f[N][N];
int main()
{
memset( f,0,sizeof(f) );
n=read(); m=read();
for ( int i=1; i<=n; i++ )
a[i]=read();
for ( int j=1; j<=m; j++ )
b[j]=read();
memset( f,0x3f,sizeof(f) ); f[0][0]=0;
for ( int i=1; i<=n; i++ )
f[i][0]=i;
for ( int j=1; j<=m; j++ )
f[0][j]=j;
for ( int i=1; i<=n; i++ )
for ( int j=1; j<=m; j++ )
if ( a[i]==b[j] ) f[i][j]=f[i-1][j-1];
else f[i][j]=min( min(f[i-1][j],f[i][j-1]),f[i-1][j-1] )+1;
printf( "%d\n",f[n][m] );
}
/*
5 10
1 2 3 4 7
1 3 7 5 4 9 9 9 9 9
8
*/
大地也该是从一片类似的光明中冒出来的。

浙公网安备 33010602011771号