解题思路:
最长公共子序列的变形题
子问题:两子串尾部元素相比较,如果相同,子串长度-1,公共子序列长度+1(这里加上对应分数)不相同则加上两子串目前所能达到的最大分数赋予公共序列;
注意事项:这里决策时一定要以最大分数为目标而不能以长度为目标,有可能存在着一个较短序列分数大于较长序列的分数
状态:dp[i][j]->c1i和c2j的目前得到分数的最大值
转移方程:dp[i][j]=dp[i-1][j-1]+score (c1i==c2j)
=max(dp[i][j-1],dp[i-1][j]) (c1i!=c2j)
/*
最长公共子序列的变形题
子问题:两子串尾部元素相比较,如果相同,子串长度-1,公共子序列长度+1(这里加上对应分数)
不相同则加上两子串目前所能达到的最大分数赋予公共序列;
注意事项:这里决策时一定要以最大分数为目标而不能以长度为目标,有可能存在着一个较短序列分数大于较长序列的分数
状态:dp[i][j]->c1i和c2j的目前得到分数的最大值
转移方程:dp[i][j]=dp[i-1][j-1]+score (c1i==c2j)
=max(dp[i][j-1],dp[i-1][j]) (c1i!=c2j)
178ms代码
*/
#include<stdio.h>
#include<string.h>
#define MAX 100010
int dp[MAX],book[MAX];
int max(int x,int y)
{
return x>y?x:y;
}
int main()
{
int i,j,n,m,x,t;
char c1[MAX],c2[MAX],c[MAX];
int map[200]={0};
while(~scanf("%d ",&t))
{
scanf("%s",c);
for(i=0;i<t;i++)
scanf("%d ",&map[c[i]]);
scanf("%s%s",c1,c2);
memset(dp,0,sizeof(dp));
memset(book,0,sizeof(book));
n=strlen(c1);
m=strlen(c2);
for(i=1;i<=n;i++)
{
x=0;
for(j=1;j<=m;j++)
{
if(c1[i-1]==c2[j-1])
dp[j]=book[j-1]+map[c1[i-1]];
else
dp[j]=max(book[j],dp[j-1]);
book[j-1]=x;
x=dp[j];
}
book[m]=x;
}
printf("%d\n",dp[m]);
}
return 0;
}