2013 Multi-University Training Contest 8
这是我第一次做多校联合的题目,虽然当时一道也没有做出来,但谁不是这样起步的呢?
1 利用贪心的思想, 先枚举a, b字符串中包含c的最短区间, 然后两次for循环求区间两端的最长公共子序列长度, 取最大值加上c的长度就是答案了
2 求最长公共子序列之前可进行预处理,这样每次处理时只要调用即可,不然可能会超时
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char a[1010], b[1010], c[1010];
int dp1[1010][1010], dp2[1010][1010];
typedef struct
{
int s;
int e;
}
ans;
ans ansa[1010], ansb[1010];
int la, lb, lc;
void DP()
{
int i, j;
char c;
for(i=0; i<=la; i++)
dp1[i][0] = 0;
for(i=1; i<=lb; i++)
dp1[0][i] = 0;
for(i=1; i<=la; i++)
for(j=1; j<=lb; j++)
{
if(a[i] == b[j])
dp1[i][j] = dp1[i-1][j-1] + 1;
else
dp1[i][j] = max(dp1[i-1][j], dp1[i][j-1]);
}
for(i=1, j=la; i < j; i++, j--)
{
c = a[i];
a[i] = a[j];
a[j] = c;
}
for(i=1, j=lb; i<j; i++, j--)
{
c = b[i];
b[i] = b[j];
b[j] = c;
}
for(i=0; i<=la; i++)
dp2[i][0] = 0;
for(i=1; i<=lb; i++)
dp2[0][i] = 0;
for(i=1; i<=la; i++)
for(j=1; j<=lb; j++)
{
if(a[i] == b[j])
dp2[i][j] = dp2[i-1][j-1] + 1;
else
dp2[i][j] = max(dp2[i-1][j], dp2[i][j-1]);
}
return;
}
int main()
{
int t, ca;
ca = 1;
scanf("%d", &t);
getchar();
while(t--)
{
int i, j, k, t1, t2, m;
gets(a + 1);
gets(b + 1);
gets(c + 1);
la = strlen(a + 1);
lb = strlen(b + 1);
lc = strlen(c + 1);
t1 = t2 = 1;
for(i=1; i<=la; i++)
{
if(a[i] == c[1])
{
k = 2;
for(j=i+1; j<=la && k<=lc; j++)
if(c[k] == a[j])
k++;
if(k-1 == lc)
{
ansa[t1].s = i;
ansa[t1++].e = j - 1;
}
}
}
for(i=1; i<=lb; i++)
{
if(b[i] == c[1])
{
k = 2;
for(j=i+1; j<=lb && k<=lc; j++)
if(b[j] == c[k])
k++;
if(k-1 == lc)
{
ansb[t2].s = i;
ansb[t2++].e = j - 1;
}
}
}
DP();
m = 0;
for(i=1; i<t1; i++)
for(j=1; j<t2; j++)
m = max(m, dp1[ansa[i].s][ansb[j].s] + dp2[la + 1 - ansa[i].e][lb + 1 - ansb[j].e]);
printf("Case #%d: %d\n", ca++, m + lc - 2);
}
return 0;
}