uva1625 Color Length

来源:互联网 发布:腾讯云服务器ubuntu 编辑:程序博客网 时间:2024/04/27 14:51

题意不说了

题解:(还是去网上搜了题解。。。)

定义dp[i][j]为第1个序列被取走了i个字符,第二个序列被取走了j个字符

定义c[i][j]为两个字符串分别被取走i,j个字符后还有多少已经开始但仍未结束的字符,这个是可以预处理出来的

而对于新序列来说,每增加一个字符,它的ans就会增加c

于是dp方程式就是:dp[i][j]=min(dp[i-1][j]+c[i-1][j],dp[i][j-1]+c[i][j-1])

实在是巧妙,表示膜拜,有兴趣可以直接去看原文:http://www.cnblogs.com/AOQNRMGYXLMV/p/4006498.html

代码的实现也是非常巧,还用了滚动数组优化空间:

code:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>const int MAXN=5005;const int inf=0x3f3f3f3f;using namespace std;char A[MAXN],B[MAXN];int sA[30],sB[30];//这里储存的是每个字符的开始位置int eA[30],eB[30];//这里储存的是每个字符的结束位置int dp[2][MAXN];int c[2][MAXN];int main(){    int T; scanf("%d",&T);    while(T--)    {        scanf("%s%s",A+1,B+1);        int lenA=strlen(A+1);        int lenB=strlen(B+1);        for(int i=1;i<=lenA;i++) A[i]-='A';        for(int i=1;i<=lenB;i++) B[i]-='A';        memset(sA,0x3f,sizeof sA);        memset(sB,0x3f,sizeof sB);        memset(eA,0,sizeof eA);        memset(eB,0,sizeof eB);//之前因为这里没清Wa了        for(int i=1;i<=lenA;i++)        {            sA[A[i]]=min(sA[A[i]],i);            eA[A[i]]=i;        }        for(int i=1;i<=lenB;i++)        {            sB[B[i]]=min(sB[B[i]],i);            eB[B[i]]=i;        }        memset(dp,0,sizeof dp);        memset(c,0,sizeof c); int t=0;        for(int i=0;i<=lenA;i++)        {            for(int j=0;j<=lenB;j++)            {                if(!i&&!j) continue;                int v1=inf,v2=inf;                if(i) v1=dp[t^1][j]+c[t^1][j];                if(j) v2=dp[t][j-1]+c[t][j-1];                dp[t][j]=min(v1,v2);//这里先做dp再更新c的原因是计算字符串长度时,长度要-1                if(i)                {                    c[t][j]=c[t^1][j];                    if(sA[A[i]]==i&&sB[A[i]]>j)  c[t][j]++;                    if(eA[A[i]]==i&&eB[A[i]]<=j) c[t][j]--;                }                else if(j)//这个else if可以保证c[0][j]只被更新一次,用dp的观点来看,相当于赋初值                {                    c[t][j]=c[t][j-1];                    if(sB[B[j]]==j&&sA[B[j]]>i)  c[t][j]++;                    if(eB[B[j]]==j&&eA[B[j]]<=i) c[t][j]--;                }            }            t^=1;        }        printf("%d\n",dp[t^1][lenB]);//不是t的原因是循环结束时t^=1    }}



原创粉丝点击