Codeforces Gym 100340I Longest Common Subpair 字符串DP
2015-09-04 23:11
597 查看
题目大意:
给出两个字符串P和Q, 找出两个字符串A和B使得A, B都是P的无交集子串, 同时也是Q的无交集的字串
问A + B的长度最长情况下, 一个A, B的解
大致思路:
字符串DP, 用dp[i][j]表示以上面P的第i个字符作为结尾和以下面Q的第j个字符作为结尾向前匹配的最大长度
然后f[i][j]表示P的长度为i的前缀和Q的长度为j的前缀的最长公共字串, 于是f[i][j]就相当于dp[i][j]的前缀和
那么将字符串倒着再来一遍, 然后枚举切割点即可, 时间复杂度O(n*n)
因为内存比较紧, 所以数组需要开short以及重复使用
代码如下:
Result : Accepted Memory : 53384 KB Time : 124 ms
/*
* Author: Gatevin
* Created Time: 2015/9/1 13:25:38
* File Name: C.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define SHOW_MEMORY(x) cout<<sizeof(x)/(1024.*1024.)<<"MB"<<endl
char s[3010];
char t[3010];
short dp[3010][3010];
short f[3010][3010];
short f2[3010][3010];
int len1, len2;
void find(int x, int y, int len)
{
for(int i = 1; i <= x; i++)
for(int j = 1; j <= y; j++)
{
if(s[i] == t[j]) dp[i][j] = dp[i - 1][j - 1] + 1;
if(dp[i][j] == len)
{
for(int k = i - len + 1; k <= i; k++)
printf("%c", s[k]);
printf("\n");
return;
}
}
}
void find2(int x, int y, int len)
{
for(int i = len1; i >= x; i--)
for(int j = len2; j >= y; j--)
{
if(s[i] == t[j]) dp[i][j] = dp[i + 1][j + 1] + 1;
if(dp[i][j] == len)
{
for(int k = i; k <= i + len - 1; k++)
printf("%c", s[k]);
printf("\n");
return;
}
}
}
int main()
{
freopen("subpair.in", "r", stdin);
freopen("subpair.out", "w", stdout);
scanf("%s", s + 1);
scanf("%s", t + 1);
len1 = strlen(s + 1);
len2 = strlen(t + 1);
for(int i = 1; i <= len1; i++)
for(int j = 1; j <= len2; j++)
if(s[i] == t[j]) dp[i][j] = dp[i - 1][j - 1] + 1;
for(int i = 1; i <= len1; i++)
for(int j = 1; j <= len2; j++)
{
f[i][j] = max(f[i][j - 1], f[i - 1][j]);
f[i][j] = max(f[i][j], dp[i][j]);
}
for(int i = len1; i >= 1; i--)
for(int j = len2; j >= 1; j--)
if(s[i] == t[j]) dp[i][j] = dp[i + 1][j + 1] + 1;
for(int i = len1; i >= 1; i--)
for(int j = len2; j >= 1; j--)
{
f2[i][j] = max(f2[i][j + 1], f2[i + 1][j]);
f2[i][j] = max(f2[i][j], dp[i][j]);
}
int maxL = 0;
int ansi = 0, ansj = 0, leni = 0, lenj = 0;
for(int i = 0; i <= len1; i++)
for(int j = 0; j <= len2; j++)
if(maxL < f[i][j] + f2[i + 1][j + 1])
{
maxL = f[i][j] + f2[i + 1][j + 1];
ansi = i, ansj = j;
leni = f[i][j], lenj = f2[i + 1][j + 1];
}
if(f[ansi][ansj] == 0 && f2[ansi + 1][ansj + 1] == 0)
{
printf("\n\n");
return 0;
}
if(f[ansi][ansj] && f2[ansi + 1][ansj + 1] == 0)
{
find(ansi, ansj, leni);
printf("\n");
return 0;
}
if(f[ansi][ansj] == 0 && f2[ansi + 1][ansj + 1])
{
printf("\n");
find2(ansi + 1, ansj + 1, lenj);
return 0;
}
find(ansi, ansj, leni);
find2(ansi + 1, ansj + 1, lenj);
return 0;
}
给出两个字符串P和Q, 找出两个字符串A和B使得A, B都是P的无交集子串, 同时也是Q的无交集的字串
问A + B的长度最长情况下, 一个A, B的解
大致思路:
字符串DP, 用dp[i][j]表示以上面P的第i个字符作为结尾和以下面Q的第j个字符作为结尾向前匹配的最大长度
然后f[i][j]表示P的长度为i的前缀和Q的长度为j的前缀的最长公共字串, 于是f[i][j]就相当于dp[i][j]的前缀和
那么将字符串倒着再来一遍, 然后枚举切割点即可, 时间复杂度O(n*n)
因为内存比较紧, 所以数组需要开short以及重复使用
代码如下:
Result : Accepted Memory : 53384 KB Time : 124 ms
/*
* Author: Gatevin
* Created Time: 2015/9/1 13:25:38
* File Name: C.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define SHOW_MEMORY(x) cout<<sizeof(x)/(1024.*1024.)<<"MB"<<endl
char s[3010];
char t[3010];
short dp[3010][3010];
short f[3010][3010];
short f2[3010][3010];
int len1, len2;
void find(int x, int y, int len)
{
for(int i = 1; i <= x; i++)
for(int j = 1; j <= y; j++)
{
if(s[i] == t[j]) dp[i][j] = dp[i - 1][j - 1] + 1;
if(dp[i][j] == len)
{
for(int k = i - len + 1; k <= i; k++)
printf("%c", s[k]);
printf("\n");
return;
}
}
}
void find2(int x, int y, int len)
{
for(int i = len1; i >= x; i--)
for(int j = len2; j >= y; j--)
{
if(s[i] == t[j]) dp[i][j] = dp[i + 1][j + 1] + 1;
if(dp[i][j] == len)
{
for(int k = i; k <= i + len - 1; k++)
printf("%c", s[k]);
printf("\n");
return;
}
}
}
int main()
{
freopen("subpair.in", "r", stdin);
freopen("subpair.out", "w", stdout);
scanf("%s", s + 1);
scanf("%s", t + 1);
len1 = strlen(s + 1);
len2 = strlen(t + 1);
for(int i = 1; i <= len1; i++)
for(int j = 1; j <= len2; j++)
if(s[i] == t[j]) dp[i][j] = dp[i - 1][j - 1] + 1;
for(int i = 1; i <= len1; i++)
for(int j = 1; j <= len2; j++)
{
f[i][j] = max(f[i][j - 1], f[i - 1][j]);
f[i][j] = max(f[i][j], dp[i][j]);
}
for(int i = len1; i >= 1; i--)
for(int j = len2; j >= 1; j--)
if(s[i] == t[j]) dp[i][j] = dp[i + 1][j + 1] + 1;
for(int i = len1; i >= 1; i--)
for(int j = len2; j >= 1; j--)
{
f2[i][j] = max(f2[i][j + 1], f2[i + 1][j]);
f2[i][j] = max(f2[i][j], dp[i][j]);
}
int maxL = 0;
int ansi = 0, ansj = 0, leni = 0, lenj = 0;
for(int i = 0; i <= len1; i++)
for(int j = 0; j <= len2; j++)
if(maxL < f[i][j] + f2[i + 1][j + 1])
{
maxL = f[i][j] + f2[i + 1][j + 1];
ansi = i, ansj = j;
leni = f[i][j], lenj = f2[i + 1][j + 1];
}
if(f[ansi][ansj] == 0 && f2[ansi + 1][ansj + 1] == 0)
{
printf("\n\n");
return 0;
}
if(f[ansi][ansj] && f2[ansi + 1][ansj + 1] == 0)
{
find(ansi, ansj, leni);
printf("\n");
return 0;
}
if(f[ansi][ansj] == 0 && f2[ansi + 1][ansj + 1])
{
printf("\n");
find2(ansi + 1, ansj + 1, lenj);
return 0;
}
find(ansi, ansj, leni);
find2(ansi + 1, ansj + 1, lenj);
return 0;
}
相关文章推荐
- Codeforces Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- Codeforces 405E Codeforces Round #238 (Div. 2)E
- Codeforces 407C Codeforces Round #239 (Div. 1)C
- CodeForces 449A - Jzzhu and Chocolate
- CodeForces 449 B. Jzzhu and Cities
- Codeforces Round #265 (Div. 2)
- Codeforces #310 div2 C. Case of Matryoshkas
- 状态压缩DP codeforces 244 Problem C. The Brand New Function 和 codeforces 165 E. Compatible Numbers
- codeforces 16 Problem E fish
- Codeforces round #247 for Div. 2
- Codeforces Round #246 (Div. 2)
- Codeforces #264(div 2)D.Gargari and Permutations
- Codeforces Round #236 (Div. 2)------A,B
- codeforces 257 div2 B
- Codeforces Gym100571A Cursed Query
- Codeforces Gym100342E Minima
- Codeforces Gym100342J Triatrip
- Codeforces Gym100286B Blind Walk (dfs)
- Codeforces Gym100342J Triatrip