歌名 - 歌手
0:00

    String

    题目

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

    分析

    \(f_{k,i,j}\)表示,当前做到第\(k\)个子串,\(S\)串的第\(i\)位,\(T\)串的第\(j\)位。
    那么转移就是,当\(S_{i}=T_{j}\)

    \[f_{k,i,j}=\max\left\{\begin{array}\\f_{k,i-1,j-1}+1(从S的这个子串第i-1位转移过来)\\f_{k-1,i`(1<=i`<=i-1),j`(1<=j`<=j-1)}+1(从S的上一个子串第i`位转移) \end{array}\right. \]

    但是,这时间复杂度是\(O(n^{2}m^{2}k)\)的。
    所以,设\(mx_{k,i,j}\)表示\(\max(f_{k,i`(1<=i`<=i),j`(1<=j`<=j)})\)
    那么转移改为$$f_{k,i,j}=\max\left{\begin{array}\f_{k,i-1,j-1}+1\mx_{k-1,i-1,j-1}+1\end{array}\right.$$
    这样,我们只要不断更新\(mx\)就可以了。

    \[mx_{k,i,j}=\max\left\{\begin{array}\\mx_{k,i-1,j}\\mx_{k,i,j-1}\\f_{k,i,j}\end{array}\right. \]

    时间复杂度是\(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);
    }
    
    posted @ 2018-05-09 12:28  无尽的蓝黄  阅读(120)  评论(0编辑  收藏  举报