ABC185E. Sequence Matching

到现在 AK 一场 ABC 还要一个多小时,我果然是一点都不行

Link

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

一开始想到编辑距离了但感觉是错的……然后敲了一个错的最长公共子序列,最后又想到这个建模……

wssb-AC

//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
*/
posted @ 2020-12-14 12:50  MontesquieuE  阅读(300)  评论(0)    收藏  举报