ACM: 变形的LCS(最长公共子序) toj…

                   Match for Bonus

描述

 

Roy played a game with his roommates the other day.

His roommates wrote 2 strings of characters, and gave each character a bonus value. When Roy pinned the positions of one common character in the 2 strings, the bonus value of that character would be added to Roy's score. However at the mean time, the 2 characters and those before them in the strings would be erased.

Roy now needs your help, because he wants to know the maximum score he can get.

输入

 

There are several test cases.

For each test case, the first line contains an integer N.

The following N lines describe a list of N characters and their bonus values.

Then the following 2 lines give the 2 strings, each string contains no more than 10000 characters.

输出

 

For each test case, output in one line the best score Roy can get.

样例输入

3
a 1
b 1
c 1
abc
bca
3
a 1
b 10
c 100
abc
cab

 

样例输出

2
100

 

题意: 如果有相同的字符, 这权值p + 相应的权值, 但是如果匹配时, 在当前字符前面的字符会全部

          消失掉.

 

题意:

         1. LCS的变形题. 原LCS题是权值+1. 现在时给定的: val[i];

         2. 一开始的思路, 确定为动态规划问题:

          问题分析:

                    (1). 方程的状态是: dp[i][j] 表示: 第一个串前i个字符到第二个串前j个字符的最大匹配权值.

                    (2). 状态转移方程:

                                        if(str1[i-1] == str2[j-1])

                                              dp[i][j] = dp[i][j-1] + val[str1[i]];

                                        dp[i][j] = max(dp[i][j] , dp[i-1][j], dp[i][j-1]);

         3. 很不幸超时了. 还是要用滚动数组. dp[2][MAX];

                            if(str1[i-1] == str2[j-1])

                                     dp[e][j] = dp[e^1][j-1] + val[str1[i-1]];

                            else

                                     dp[e][j] = max(dp[e^1][j],dp[e][j-1]);

            锯齿状.

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 10005
int dp[2][MAX];
char str1[MAX], str2[MAX];
int val[MAX];
int n;
inline int max(int a,int b)
{
 return a > b ? a : b;
}
int main()
{
 int i, j;
// freopen("input.txt","r",stdin);
 while(scanf("%d",&n) != EOF)
 {
  memset(val,0,sizeof(val));
  memset(dp,0,sizeof(dp));
  char ch;
  int v;
  for(i = 0; i < n; ++i)
  {
   getchar();
   scanf("%c %d",&ch,&v);
   val[ch] = v;
  }
  scanf("%s %s",str1,str2);
  dp[0][0] = 0;
  int len1 = strlen(str1);
  int len2 = strlen(str2);
  int e = 0;
  for(i = 1; i <= len1; ++i)
  {
   e ^= 1;
   for(j = 1; j <= len2; ++j)
   {
    if(str1[i-1] == str2[j-1])
     dp[e][j] = dp[e^1][j-1] + val[str1[i-1]];
    else
     dp[e][j] = max(dp[e^1][j],dp[e][j-1]);
   }
  }
  printf("%d\n",dp[e][len2]);
 }
 return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值