pku acm 1080

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <map>
using namespace std;

map<string,int> dicm;//字典
void myinit()//初始化字典
{
	dicm.insert(make_pair("AA",5));
	dicm.insert(make_pair("AC",-1));
	dicm.insert(make_pair("AG",-2));
	dicm.insert(make_pair("AT",-1));
	dicm.insert(make_pair("A-",-3));

	dicm.insert(make_pair("CA",-1));
	dicm.insert(make_pair("CC",5));
	dicm.insert(make_pair("CG",-3));
	dicm.insert(make_pair("CT",-2));
	dicm.insert(make_pair("C-",-4));

	dicm.insert(make_pair("GA",-2));
	dicm.insert(make_pair("GC",-3));
	dicm.insert(make_pair("GG",5));
	dicm.insert(make_pair("GT",-2));
	dicm.insert(make_pair("G-",-2));

	dicm.insert(make_pair("TA",-1));
	dicm.insert(make_pair("TC",-2));
	dicm.insert(make_pair("TG",-2));
	dicm.insert(make_pair("TT",5));
	dicm.insert(make_pair("T-",-1));

	dicm.insert(make_pair("-A",-3));
	dicm.insert(make_pair("-C",-4));
	dicm.insert(make_pair("-G",-2));
	dicm.insert(make_pair("-T",-1));
}


int simility(string s1,string s2)//求字符串s1与s2的相似度(常规解法--类似于求最大公共序列)
{
	string s;
	int sum = 0;
	if(s1.size() == 0)
	{		
		for(int i = 0; i < s2.size(); i++)
		{
			s = "-";
			s += s2[i];
			sum += dicm[s];
		}
		return sum;
	}
	else if(s2.size() == 0)
	{
		for(int i = 0; i < s1.size(); i++)
		{
			s = s1[i];
			s += "-";
			sum += dicm[s];
		}
		return sum;
	}


	//case 1:
	int result1;
	{			
		s =  s1[s1.size()-1];
		s += s2[s2.size()-1];

		string ts1 = s1,ts2 = s2;
		ts1.erase(ts1.size()-1);
		ts2.erase(ts2.size()-1);
		result1 = simility(ts1,ts2)+dicm[s];
	}

	//case 2:
	int result2;
	{
		s =  s1[s1.size()-1];
		s += "-";

		string ts1 = s1,ts2 = s2;
		ts1.erase(ts1.size()-1);		
		result2 = simility(ts1,ts2)+dicm[s];
	}

	//case 3:
	int result3;
	{
		s =  "-";
		s += s2[s2.size()-1];

		string ts1 = s1,ts2 = s2;
		ts2.erase(ts2.size()-1);		
		result3 = simility(ts1,ts2)+dicm[s];
	}
	
	return max(result1,max(result2,result3));
}

int r[102][102];
int len1,len2;// 1 <= len1,len2 <= 100
int simility2(string s1,string s2)//求字符串s1与s2的相似度(动态规划解法)
{
	for(int i = 0; i < len1; i++)
	{
		for(int j = 0; j < len2; j++)
		{
			string s;
			int result1;//case 1
			{
				s = s1[i];
				s += s2[j];
				if(i-1 >= 0 && j-1 >= 0)
					result1 = r[i-1][j-1] + dicm[s];
				else if(i-1 < 0)
				{
					if(j-1 >= 0)
					{
						int sum = 0;
						string ts;
						for(int k = 0; k <= j-1; k++)
						{
							ts = '-';
							ts += s2[k];
							sum += dicm[ts];
						}
						result1 = sum + dicm[s];
					}
					else
						result1 = dicm[s];
				}
				else if(j-1 < 0)
				{
					int sum = 0;
					string ts;
					for(int k = 0; k <= i-1; k++)
					{
						ts = s1[k];
						ts += '-';
						sum += dicm[ts];
					}
					result1 = sum + dicm[s];
				}

			}

			int result2;//case 2
			{
				s = '-';
				s += s2[j];

				if(j-1 >= 0)
					result2 = r[i][j-1] + dicm[s];
				else// j-1 < 0
				{				
					int sum = 0;
					string ts;
					for(int k = 0; k <= i; k++)
					{
						ts = s1[k];
						ts += '-';
						sum += dicm[ts];
					}
					result2 = sum + dicm[s];
				}
			}
			
			int result3;//case3
			{
				s = s1[i];
				s += '-';

				if(i-1 >= 0)
					result3 = r[i-1][j] + dicm[s];
				else// i-1 < 0
				{				
					int sum = 0;
					string ts;
					for(int k = 0; k <= j; k++)
					{
						ts = '-';
						ts += s2[k];
						sum += dicm[ts];
					}
					result3 = sum + dicm[s];
				}
			}

			r[i][j] = max(result1,max(result2,result3));
		}
	}

	return r[len1-1][len2-1];
}

int main()
{	
	freopen("in.txt","r",stdin);
	myinit();

	int t; // 1 <= t <= 10
	
	string s1,s2;
	cin>>t;
	while(t--)
	{		
		cin>>len1>>s1>>len2>>s2;
		cout<<"sim1 = "<<simility(s1,s2)
			<<" sim2 = "<<simility2(s1,s2)<<endl;
	}
	return 1;
}


测试用例:

7
2 AG
1 G

1 A
1 G

2 GT
1 A

2 AG
2 GT


3 AGT
3 GTT

7 AGTGATG
5 GTTAG

7 AGCTATT
9 AGCTTTAAA


动态规划算法思想:

1,很明显此题满足最优子结构性质

2,

index of s1 0





i











s1



















index of s2 0







j









s2



















最大匹配度为:

r[ i ] [ j ]  = max( r(s1[0 ... i-1] , s2[0... j-1]) + dicm[  s1[i] s2[j]  ],   

                         r( s1[0 ... i] , s2[0... j-1] ) + dicm[  - s2[j]  ],   

                         r( s1[0 ... i-1] , s2[0... j ] ) + dicm[ s1[i]  - ]   

                       ),其中 0 <= i <= s1.size()-1, 0 <= j <= s2.size() - 1; 注意边界情况,即i - 1 < 0 , j - 1< 0 的情况

最大匹配度即为r[s1.size() - 1] [ s2.size() - 1]

你可能感兴趣的:(pku acm 1080)