UVa1625 Color Length

        是不是和最长公共子序列很像?对,就是那样dp,不过需要预处理每个颜色开始的位置和结束的位置,才能知道放入这个颜色后,会使结果增加多少。这题开始我一直TLE。。原因是我用memset()初始化5000*5000的数组,才知道那个函数在数据大的时候耗时是多么可怕!


#include <iostream>      
#include <stdio.h>      
#include <cmath>      
#include <algorithm>      
#include <iomanip>      
#include <cstdlib>      
#include <string>      
#include <memory.h>      
#include <vector>      
#include <queue>      
#include <stack>      
#include <map>    
#include <set>    
#include <ctype.h>      
#define INF 10000  
#define ll long long  
#define max3(a,b,c) max(a,max(b,c))  
#define MAXN 100010  

using namespace std;

char str1[5010];
char str2[5010];

int first[26][2];
int last[26][2];

int dp[5010][5010];
int tab[5010][5010];


int main(){
    int t;
    cin>>t;
    while(t--){
        scanf("%s%s",str1+1,str2+1);                         
        int len1=strlen(str1+1);
        int len2=strlen(str2+1);
        memset(first,-1,sizeof(first));
        memset(last,-1,sizeof(last));
        
        for(int i=1;i<=len1;i++){
            if(first[str1[i]-65][1]==-1 )
                first[str1[i]-65][1]=i;
        }
        for(int i=1;i<=len2;i++){
            if(first[str2[i]-65][0]==-1 )
                first[str2[i]-65][0]=i;
        }
        //
        for(int i=len1;i>=1;i--){
            if(last[str1[i]-65][1]==-1 )
                last[str1[i]-65][1]=i;
        }
        for(int i=len2;i>=1;i--){
            if(last[str2[i]-65][0]==-1 )
                last[str2[i]-65][0]=i;
        }
        //
        for(int i=0;i<=len1;i++){
			for(int j=0;j<=len2;j++){
				int re=0;
				for(int k=0;k<26;k++){
			        if( (  (i>=first[k][1]&&first[k][1]!=-1)  || (j>=first[k][0]&&first[k][0]!=-1  )) &&
			            ( (i<last[k][1] &&last[k][1]!=-1)|| (j<last[k][0]&&last[k][0]!=-1) ) ){                   
			            re++;
			        }
			    }
			    tab[i][j]=re;
			}
		}
        
        dp[0][0]=0;
        for(int i=1;i<=len1;i++){
            dp[i][0]=dp[i-1][0]+tab[i][0];
        }
        for(int i=1;i<=len2;i++){
            dp[0][i]=dp[0][i-1]+tab[0][i];
        }
        
        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){
                dp[i][j]=min( dp[i-1][j] , dp[i][j-1] )+tab[i][j];
            }
        }
        cout<<dp[len1][len2]<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值