#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]