带跨越式的LCS,同样是在朴素的LCS上加入一种跨越一段的转移,这样我们要预处理出跨越一段给定串的转移函数。
这个题同样可以正反两边LCS做
呆马:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #define inf 0x3f3f3f3f 7 #define maxn 1020 8 9 using namespace std; 10 11 char s[maxn],t[maxn],d[maxn]; 12 int f[2][maxn][maxn],bs[maxn][maxn],bt[maxn][maxn]; 13 14 int main() 15 { 16 int Case; 17 scanf("%d",&Case); 18 for (int o=1;o<=Case;o++) 19 { 20 scanf(" %s %s %s",s+1,t+1,d+1); 21 int ls=strlen(s+1), lt=strlen(t+1), ld=strlen(d+1); 22 memset(bs,0,sizeof(bs)); 23 24 for (int i=1;i<=ls;i++) 25 if (s[i]==d[1]) bs[1][i]=i; 26 else bs[1][i]=bs[1][i-1]; 27 for (int i=2;i<=ld;i++) 28 for (int j=1;j<=ls;j++) 29 if (s[j]==d[i]) bs[i][j]=bs[i-1][j-1]; 30 else bs[i][j]=bs[i][j-1]; 31 32 memset(bt,0,sizeof(bt)); 33 34 for (int i=1;i<=lt;i++) 35 if (t[i]==d[1]) bt[1][i]=i; 36 else bt[1][i]=bt[1][i-1]; 37 for (int i=2;i<=ld;i++) 38 for (int j=1;j<=lt;j++) 39 if (t[j]==d[i]) bt[i][j]=bt[i-1][j-1]; 40 else bt[i][j]=bt[i][j-1]; 41 42 memset(f,0,sizeof(f)); 43 for (int i=1;i<=ls;i++) 44 for (int j=1;j<=lt;j++) 45 { 46 f[0][i][j]=max(f[0][i-1][j],f[0][i][j-1]); 47 f[1][i][j]=max(f[1][i-1][j],f[1][i][j-1]); 48 if (s[i]==t[j]) 49 { 50 f[0][i][j]=max(f[0][i][j],f[0][i-1][j-1]+1); 51 if (f[1][i-1][j-1]) 52 f[1][i][j]=max(f[1][i][j],f[1][i-1][j-1]+1); 53 } 54 if (bs[ld][i] && bt[ld][j]) 55 f[1][i][j]=max(f[1][i][j],f[0][bs[ld][i]-1][bt[ld][j]-1]+ld); 56 } 57 printf("Case #%d: %d\n",o,f[1][ls][lt]); 58 } 59 return 0; 60 }