zoukankan      html  css  js  c++  java
  • 【水题】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

  • 相关阅读:
    Microjs: 超棒的迷你框架和迷你类库搜罗工具
    本周推荐7款CSS3实现的动态特效
    Bootstrap3.1开发的响应式个人简历模板
    10分钟,利用canvas画一个小的loading界面
    四款超棒的jQuery数字化签名插件
    搜索引擎优化网页设计:最佳实践
    推荐超实用的8款jQuery插件
    9款HTML5实现的超酷特效
    想成为程序猿?28个在线学习网站让你变身齐天大圣!
    推荐7款超棒的单页面网站设计模板。关键是!免费!!
  • 原文地址:https://www.cnblogs.com/Hathawaxy/p/7749266.html
Copyright © 2011-2022 走看看