水题luogu-2679 子串

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了水题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

以上是关于水题luogu-2679 子串的主要内容,如果未能解决你的问题,请参考以下文章

luogu P2679——子串

[luogu2679] 子串 (多维dp)

POJ 1936 All in All 匹配, 水题 难度:0

快乐水题686. 重复叠加字符串匹配

HDU 5907 Find Q (水题)

UVA - 10391:Compound Words (字符串水题)