您的位置:首页 > 大数据 > 人工智能

Codeforces Gym 100340I Longest Common Subpair 字符串DP

2015-09-04 23:11 525 查看
题目大意:

给出两个字符串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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息