解题思路:

最长公共子序列的变形题

子问题:两子串尾部元素相比较,如果相同,子串长度-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;
}