String

来源:互联网 发布:mac 添加歌曲至资源 编辑:程序博客网 时间:2024/06/07 22:42

题目

有两种字符串S,T。长度分别为n,m。现在需要在S里面有序地选出k个子串,且在T中出现的顺序与这k个子串的顺序相同。问这k个子串最大的长度和

分析

fk,i,j表示,当前做到第k个子串,S串的第i位,T串的第j位。
那么转移就是,当Si=Tj

fk,i,j=max{fk,i1,j1+1Si1fk1,i1<=i<=i1,j1<=j<=j1+1Si

但是,这时间复杂度是O(n2m2k)的。
所以,设mxk,i,j表示max(fk,i1<=i<=i,j1<=j<=j)
那么转移改为
fk,i,j=max{fk,i1,j1+1mxk1,i1,j1+1

这样,我们只要不断更新mx就可以了。
mxk,i,j=maxmxk,i1,jmxk,i,j1fk,i,j

时间复杂度是O(nmk)

#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>const int maxlongint=2147483647;const int mo=1000000007;const int N=1005;using namespace std;int g[N][N],n,m,k,tot,ans,next[N],f[12][N][N],mx[12][N][N];char s[N],t[N];int main(){    freopen("string.in","r",stdin);    freopen("string.out","w",stdout);    scanf("%d%d%d\n",&n,&m,&k);    scanf("%s\n",s+1);    scanf("%s\n",t+1);    for(int l=1;l<=k;l++)        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)            {                if(s[i]==t[j])                {                    f[l][i][j]=max(f[l][i-1][j-1],mx[l-1][i-1][j-1])+1;                }                mx[l][i][j]=max(mx[l][i][j-1],max(mx[l][i-1][j],f[l][i][j]));                ans=max(ans,f[l][i][j]);            }    printf("%d",ans);}
1 0
原创粉丝点击