HDU 4681 String

来源:互联网 发布:小米手环抢购软件 编辑:程序博客网 时间:2024/06/07 16:18

http://acm.hdu.edu.cn/showproblem.php?pid=4681

蛮好……

一开始有这样的想法:dp[i][j][k]=lcs(A[1..i],B[1..j]),ending with C[1...k],不过当然是过不了的。

其实 C 没有必要分开考虑,只要找到有 C 做子序列的位置【A 里面和 B 里面】,剩下的部分可以分别解决。

具体说来就是:

  1. lcs_lft[i][j]=lcs(A[1..i],B[1..j])lcs_rit[i][j]=lcs(A[i..n],B[j..m])

  2. A 的每个位置i有一个 j=nexta[i]的位置,表示 A[i..j]有一个 C 做子序列并且j尽量小;同理有 nextb[]

  3. result=max(lcs_lft[i1][j1]+lcs_rit[nexta[i]+1][nextb[j]+1])+strlen(C)

#include <bits/stdc++.h>const int N = 1024;char a[N];char b[N];char c[N];int lcs_lft[N][N];int lcs_rit[N][N];int nexta[N];int nextb[N];void lcs_table(int n, int m){  memset(lcs_lft, 0, sizeof(lcs_lft));  memset(lcs_rit, 0, sizeof(lcs_rit));  for (int i = 1; i <= n; ++i)  {    for (int j = 1; j <= m; ++j)    {      lcs_lft[i][j] = std::max(lcs_lft[i - 1][j], lcs_lft[i][j - 1]);      if (a[i] == b[j])        lcs_lft[i][j] = std::max(lcs_lft[i - 1][j - 1] + 1, lcs_lft[i][j]);    }  }  for (int i = n; i >= 1; --i)  {    for (int j = m; j >= 1; --j)    {      lcs_rit[i][j] = std::max(lcs_rit[i + 1][j], lcs_rit[i][j + 1]);      if (a[i] == b[j])        lcs_rit[i][j] = std::max(lcs_rit[i + 1][j + 1] + 1, lcs_rit[i][j]);    }  }}void next_table(int n, int m){  for (int i = 1; i <= n; i++)  {    int len = 0;    nexta[i] = -1;    for (int j = i; j <= n; j++)    {      if (a[j] == c[len + 1])      {        len++;        if (c[len + 1] == '\0')        {          nexta[i] = j;          break;        }      }    }  }  for (int i = 1; i <= m; i++)  {    int len = 0;    nextb[i] = -1;    for (int j = i; j <= m; j++)    {      if (b[j] == c[len + 1])      {        len++;        if (c[len + 1] == '\0')        {          nextb[i] = j;          break;        }      }    }  }}int max_length(int n, int m){  int res = 0;  for (int i = 1; i <= n; i++)  {    for (int j = 1; j <= m; j++)    {      int ii = nexta[i];      int jj = nextb[j];      if (ii < 0 || jj < 0)        continue;      int tmp = lcs_lft[i - 1][j - 1] + lcs_rit[ii + 1][jj + 1];      res = std::max(res, tmp);    }  }  res += strlen(c + 1);  return res;}int main(){  int casc;  scanf("%d", &casc);  for (int casi = 1; casi <= casc; casi++)  {    scanf("%s %s %s", a + 1, b + 1, c + 1);    int n = strlen(a + 1);    int m = strlen(b + 1);    lcs_table(n, m);    next_table(n, m);    printf("Case #%d: %d\n", casi, max_length(n, m));  }  return 0;}
0 0
原创粉丝点击