Codeforces Gym 100340I Longest Common Subpair 字符串DP

来源:互联网 发布:linux进程查看命令 top 编辑:程序博客网 时间:2024/06/07 08:19

题目大意:

给出两个字符串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"<<endlchar 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;}


0 0
原创粉丝点击