poj1080

本文介绍了一种使用动态规划解决特定字符串匹配问题的方法。通过在两个输入字符串间插入字符“-”来达到最大匹配值的目的,同时保持原有字符顺序不变。文章详细解析了状态转移方程,并附上了实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目有难度,有点类似于lcs的分析,题目大意为:每个case给定两个字符串,要求在两个串中插入必要的‘-‘使得两串匹配按照题目所给定value值最大。理解题意时要注意如下:

1)只能在原串中插入字符’-‘,使得两串的长度相等,但原串本身字符的顺序不能改变,这是该题的关键点

2)可以在任意位置插入任意数量的’-‘,只要不违反条件1)

理解了上述两点后,接着就要确定dp及状态方程了。分析如下:

我们令dp[i][j]表示第一个串中前i个字符,第二个串中前j个字符,所组成的两个字符串的最大value。则第二个字符串中最末尾的字符next[j]可以与第一个字符串中的字符first[k]匹配(1<=k<=i ),同时可以匹配符号‘-’,而匹配符号可以分为多种情况,符号‘-’的位置不同,则表达式就不同,但均可以归为一种情况即:dp[i][j-1]+value[1][next[j]-'A']。

那么动态转移方程就出来了:dp[i][j]=max{dp[k-1][j-1]+value[first[k]-'A'][next[j]-'A']+value[1][first[index]-'A']}

详细见代码: 204K+32MS

#include <stdio.h>
#include <stdlib.h>
#define Max 110
#define Maxx(a,b) (a)>(b)?(a):(b)
char first[Max]; // 第一个串
char next[Max]; // 第二个串
char help[Max]; // 辅助数组
int dp[Max][Max]; 
int value[20][20]; //记录题意value
int Case;
int len1,len2; // 串长1和2
int main(){
	int i,j,k,index; //初始化题意value
	value[0][0]=5,value[0][1]=-3,value[0][2]=-1,value[0][6]=-2,value[0][19]=-1;
	value[2][0]=-1,value[2][1]=-4,value[2][2]=5,value[2][6]=-3,value[2][19]=-2;
	value[6][0]=-2,value[6][1]=-2,value[6][2]=-3,value[6][6]=5,value[6][19]=-2;
	value[19][0]=-1,value[19][1]=-1,value[19][2]=-2,value[19][6]=-2,value[19][19]=5;
	value[1][0]=-3,value[1][2]=-4,value[1][6]=-2,value[1][19]=-1;
	scanf("%d",&Case);
	while(Case--){
		scanf("%d",&len1);
		getchar();
		scanf("%s",help); //转化为第一个串,以1开头
		for(i=1;i<=len1;i++)
			first[i]=help[i-1];
		scanf("%d",&len2);
		getchar();
		scanf("%s",help);
		for(i=1;i<=len2;i++) // 同理
			next[i]=help[i-1];
		dp[0][0]=0; //初始化两个长度均为0的串匹配最大value为0
//初始化第二个串长度为0,第一个串长度为i(1<=i<=len1)匹配的最大长度即为第一个串中的每个字符与符号’-‘匹配
		for(i=1;i<=len1;i++){
                           dp[i][0]=0; 
			for(j=1;j<=i;j++)
				dp[i][0]+=value[1][first[j]-'A'];
		}
//同理,初始化第一个串长度为0
		for(i=1;i<=len2;i++){
			dp[0][i]=0;
			for(j=1;j<=i;j++)
				dp[0][i]+=value[1][next[j]-'A'];
		}
		for(i=1;i<=len1;i++) //求解dp,注意顺序必须为这样,才能利用已知dp求解未知dp
			for(j=1;j<=len2;j++){
                                     //两种特殊情况,特殊处理,分别为末尾匹配和与’-‘匹配
				dp[i][j]=dp[i-1][j-1]+value[first[i]-'A'][next[j]-'A']; 
				dp[i][j]=Maxx(dp[i][j],dp[i][j-1]+value[1][next[j]-'A']);
				for(k=1;k<i;k++){ // 一般情况,当1<=k<i时
					int temp=dp[k-1][j-1]+value[first[k]-'A'][next[j]-'A'];
					for(index=k+1;index<=i;index++)
						temp+=value[1][first[index]-'A'];
					dp[i][j]=Maxx(dp[i][j],temp);
				}
			}
		printf("%d\n",dp[len1][len2]); //输出最大value
	}
	return 0;
}


 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值