• 【水题】luogu-2679 子串


    这道题应该是noip原题,因为dp方程式比较难推,所以也想写个题解好好整理一下。

    首先,因为太菜,第一次看到这个题,只能想到暴力拿部分分,连dp都没去想。

    后来知道是dp以后,我也想不出转移方程,所以看了题解。

    分析:

    有dp[i,j,k,x]表示A串前i个字符去匹配B串前j个字符分成k个部分(在x的状态下)

    x=0或1,分别表示A串第i位和B串第j位匹不匹配

    比较明显,如果a[i]=b[1]  f[i,1,1,1]:=1; 

    所以f[i,1,1,0]:=sum(f[1~i,1,1,1]);

    以上是预处理。

    接下来进入dp状态转移。

    f[i,j,k,1]:=f[i-1,j-1,k-1,1]+f[i-1,j-1,k-1,0]+f[i-1,j-1,k,1];

    分别表示A串第i位和B串第j位匹配时,总方案为 A串第i-1位和B串第j-1匹配时取,不匹配,不取  方案之和。

    f[i,j,k,0]:=f[i-1,j,k,0]+f[i-1,j,k,1];

    表示A串第i位和B串第j位不匹配时,总方案为   A串第i-1位和B串第j位不匹配 和匹配 的方案数之和

    现在放上没有加过优化的程序

    const p=1000000007;
    var n,m,kk,i,j,k,s:longint;
    a,b:ansistring;
    f:array[0..500,0..50,0..50,0..1]of longint;
    //f[i,j,k,x]表示A串前i个字符使用k个子串匹配B串前j个字符
    //x=0表示第i位不使用,x=0表示第i位使用
    begin
        readln(n,m,kk);
        readln(a);
        readln(b);
        for i:=1 to n do 
            begin
                f[i,1,1,0]:=s mod p;
                if a[i]=b[1] then 
                    begin
                        f[i,1,1,1]:=1;
                        inc(s);
                    end;
                for j:=2 to m do
                    for k:=1 to kk do
                        begin
                            if a[i]=b[j] then 
                            f[i,j,k,1]:=((f[i-1,j-1,k-1,1]+f[i-1,j-1,k-1,0]) mod p+f[i-1,j-1,k,1]) mod p;
                            f[i,j,k,0]:=(f[i-1,j,k,0]+f[i-1,j,k,1]) mod p;
                        end;
            end;
        writeln((f[n,m,kk,0]+f[n,m,kk,1])mod p);
    end.

    然后因为内存的原因,本题需要加滚动数组。

    const p=1000000007;
    var n,m,kk,i,j,k,s,now:longint;
    a,b:ansistring;
    f:array[0..1,0..200,0..200,0..1]of longint;
    //f[i,j,k,x]表示A串前i个字符使用k个子串匹配B串前j个字符
    //x=0表示第i位不使用,x=0表示第i位使用
    begin
        readln(n,m,kk);
        readln(a);
        readln(b);
        now:=1; s:=0;
        for i:=1 to n do 
            begin
                now:=1-now;
                fillchar(f[now],sizeof(f[now]),0);
                f[now,1,1,0]:=s mod p;
                if a[i]=b[1] then 
                    begin
                        f[now,1,1,1]:=1;
                        inc(s);
                    end;
                for j:=2 to m do
                    for k:=1 to kk do
                        begin
                            if a[i]=b[j] then 
                            f[now,j,k,1]:=((f[1-now,j-1,k-1,1]+f[1-now,j-1,k-1,0]) mod p+f[1-now,j-1,k,1]) mod p;
                            f[now,j,k,0]:=(f[1-now,j,k,0]+f[1-now,j,k,1]) mod p;
                        end;
            end;
        writeln((f[now,m,kk,0]+f[now,m,kk,1])mod p);
    end.

     2017-10-29 06:55:26 Hathaway

  • 相关阅读:
    AsyncTask类
    linux下带有空格的文件怎么删除
    python 获取指定文件夹的大小
    python 无法获取隐藏文件夹中的文件列表
    LINK : fatal error LNK1104: 无法打开文件“libboost_serialization-vc90-mt-gd-1_62.lib”
    解决错误 fatal error C1010: unexpected end of file while looking for precompiled head
    PCH Warning: header stop cannot be in a macro or #if block.
    C++ Boost在VS2015中的使用
    dev-c++ boost库的安装
    python 获取命令行输出结果
  • 原文地址:https://www.cnblogs.com/Hathawaxy/p/7749266.html
Copyright © 2020-2023  润新知