简单线性dp

  小zc现在有三个字符串,他想知道前两个字符串能不能生成第三个字符串,生成规则如下:第一个串的每个字符都可以往第二个串的任意位置插入(包括首尾位置),但必须保证来源于第一个串中的字符在生成后的串中的相对顺序不可以改变。

举个例子:
        String A: cu
        String B: mt
    那么,A和B可以生成的所有字符串是{cumt,cmut,cmtu,mcut,mctu,mtcu},而不能生成ucmt,因为uc来源于A串,但改变了A中字符原来的相对顺序。
    但小zc觉得这个问题太简单,于是他想让你计算对于给定的A, B, C串,共有多少种方案能够生成C串。方便起见,你只需要输出最后答案对1000000007取模的值。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#define rep(i,l,r)  for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std;
const int mod = 1e9+7;
const int N = 3000;
int l1,l2,l3,dp[N][N]; 
//dp[i][j]表示已经匹配了s1前i个字符,s2前j个字符的方案数
char s1[N],s2[N],s3[N*2];
 
void solve() {
    memset(dp,0,sizeof(dp));
    dp[0][0] =1;
    rep(i,1,l1) {
        if(s1[i] == s3[i]) 
            dp[i][0] = dp[i-1][0];
    }
    rep(i,1,l2) {
        if(s2[i] == s3[i]) 
            dp[0][i] = dp[0][i-1];
    }
 
    rep(i,1,l1) {
        rep(j,1,l2) {
            if(s1[i] == s3[i+j]) {
                dp[i][j] = (dp[i][j] + dp[i-1][j]) %mod;
            }
            if(s2[j] == s3[i+j]) {
                dp[i][j] = (dp[i][j] + dp[i][j-1]) %mod;
            }           
        }
    }
    cout << dp[l1][l2] <<endl; 
}
 
int main(){
    int T; scanf("%d",&T);
    while (T--) {
        scanf("%s %s %s",s1+1,s2+1,s3+1);
        l1 = strlen(s1+1);
        l2 = strlen(s2+1);
        l3 = strlen(s3+1);
        solve();
    }
    return 0;
}

 

posted @ 2018-08-18 11:22  Draymonder  阅读(271)  评论(0编辑  收藏  举报