zoukankan      html  css  js  c++  java
  • 题解 lg2679 子串 --线性dp

    题意

    有两个仅包含小写英文字母的字符串A 和B。

    现在要从字符串 A 中取出 k个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A中出现的顺序依次连接起来得到一个新的字符串。请问有多少种方案可以使得这个新串与字符串 B相等

    思路

    我最开始并没有想到DP

    最开始以为是一道字符串的题目,不过问题方案与数据范围提示我们这道题其实可以DP

    (f_{i,j,k})表示A以(i)为结尾,B以第(j)位为结尾,一共取了(k)个子串的方案数

    那么可以得到以下DP式子

    [f_{i,j,k}=egin{cases} f_{i-1,j,k},A_i eq B_j \f_{i-1,j,k}+f_{i-1,j-1,k-1},A_i= B_j\f_{i-1,j,k}+f_{i-1,j-1,k-1}+f_{i-2,j-2,k-1},A_i=B_j,A_{i-1}=B_{j-1}\...end{cases} ]

    可以发现DP式只与(i,i-1)有关,就可以用类似01背包滚动数组的方法来优化空间

    另外,我们会发现如果有相等的字符,那么求值会新添一个循环,我们可以考虑记录相等字符带来的贡献,即用(sum_{j,k})表示在B以第(j)位为结尾,一共取了(k)个子串时的第j位与其之前连续的相等字符的贡献.

    [sum_{j,k}=egin{cases}0,A_i eq B_j \sum_{j-1,k}+f_{j-1,k-1},A_i=B_jend{cases} ]

    其实就是对(f_{i-1,j-1,k-1}+f_{i-2,j-2,k-1}+...)的求和

    这样就好了

    时间复杂度(O(nmk)),空间复杂度(O(mk))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int const MOD=1e9+7;
    int n,m,nk;
    char A[1010],B[1010];
    int f[210][210]={1},sum[210][210];
    int main(){
    	scanf("%d%d%d%s%s",&n,&m,&nk,A+1,B+1);
    	for(int i=1;i<=n;i++){
    		for(int j=m;j>=1;j--){
    			for(int k=nk;k>=1;k--){
    				f[j][k]=(f[j][k]+(sum[j][k]=(A[i]==B[j]?sum[j-1][k]+f[j-1][k-1]:0)%MOD))%MOD;
    			}
    		}
    	}
    	printf("%d
    ",f[m][nk]);
    	return 0;
    }
    
  • 相关阅读:
    Visual Studio LightSwitch
    Android 虚拟机与真机调试配置
    点击手机 menu 硬件按钮后的显示及处理
    Windows Phone 7 真机调试
    Android 调试
    Android 新建项目 页面
    今天我的Windows Phone 7 HTC HD7 手机 升级 NoDo 了 分享一下经验
    Activity 之间调用与参数传递
    Android widget 组件
    解决 warning: found plain 'id' attribute; did you mean the new 'android:id' name? 问题
  • 原文地址:https://www.cnblogs.com/fpjo/p/13949483.html
Copyright © 2011-2022 走看看