您的位置:首页 > 其它

TC SRM601 div2 p1000

2013-12-23 15:34 162 查看

题目大意

给三个字符串A,B,C,求一个字符串S,其中,S是A和B的子序列,同时C是S的子串,求S最长的长度

解题思路

首先,S一定是A和B公共子序列,那么首先求LIS是一定的了,但是问题就在于怎么把C给放进去
对于A和B的每一个位置,我们可以依次对C里面的所有字符寻找,知道找到C的尾部,然后将此位置开始,依次匹配完C的所有字符之后的最后一个位置记录下来,如果没有的话就标记为无法匹配,然后对A和B正向反向分别求一边LIS,然后,枚举A和B的每一个位置,答案应该就是到当前位置的正向LIS,加上A和B的当前位置匹配完C以后的最后一个位置到最后的反向LIS,加上C的长度就应该是当前位置所得到的一个解,然后所有的位置取一个最大值,就是最终的答案。

代码

int firstA[2505], firstB[2505], lis[2505][2505], lis1[2505][2505];
class WinterAndReindeers {
public:
void getlis(int lis[][2505], string A, string B){
for (int i = 0; i < A.size(); i++)
for (int j = 0; j < B.size(); j++){
if (i) lis[i][j] = lis[i - 1][j];
if (j) lis[i][j] = max(lis[i][j], lis[i][j - 1]);
if (A[i] == B[j])
lis[i][j] = max(lis[i][j], ((i && j) ? lis[i - 1][j - 1] : 0) + 1);
}
}
int getNumber(vector <string> allA, vector <string> allB, vector <string> allC) {
string A = "", B = "", C = "";
for (int i = 0; i < allA.size(); i++) A += allA[i];
for (int i = 0; i < allB.size(); i++) B += allB[i];
for (int i = 0; i < allC.size(); i++) C += allC[i];
for (int i = 0; i < A.size(); i++){
int j, k;
for (j = 0, k = i; j < C.size() && k < A.size(); k++)
if (C[j] == A[k]) j += 1;
if (j == C.size()) firstA[i] = k;
else firstA[i] = -1;
}
for (int i = 0; i < B.size(); i++){
int j, k;
for (j = 0, k = i; j < C.size() && k < B.size(); k++)
if (C[j] == B[k]) j += 1;
if (j == C.size()) firstB[i] = k;
else firstB[i] = -1;
}
getlis(lis, A, B);
reverse(A.begin(), A.end());
reverse(B.begin(), B.end());
getlis(lis1, A, B);
int ans = 0;
for (int i = 0; i < A.size(); i++)
for (int j = 0; j < B.size(); j++){
if (firstA[i] == -1 || firstB[j] == -1) continue;
int tmp = (i && j) ? lis[i - 1][j - 1] : 0;
int l1 = A.size() - 1 - firstA[i];
int l2 = B.size() - 1 - firstB[j];
int tmp1 = (l1 >= 0 && l2 >= 0) ? lis1[l1][l2] : 0;
ans = max(tmp + (int)C.size() + tmp1, ans);
}
return ans;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: