LCS长度个数计算

来源:互联网 发布:塞内加 知乎 编辑:程序博客网 时间:2024/05/10 01:36

子串

给定一个字符串 A1..n

对于任意一个集合 G1..m 并且 1G1<G2<<Gmn

那么 AG1..m 就是 A 的一个子串

如:

AABC 就是ABCABC的一个子串

LCS

给定两个字符串 A,B ,求出他们最长的公共子串 C

意思是: C 既是 A 的子串,又是 B 的子串

求法

先给出代码:

#define mod 1000000007#define N 5010int n,m,f[N][N],h[N][N],ans;char s1[N],s2[N];int main(){    scanf("%s%s",s1+1,s2+1);    n=strlen(s1+1);    m=strlen(s2+1);    fr(i,1,n)        f[i][0]=1;    fr(i,0,m)        f[0][i]=1;    fr(i,1,n)        s1[i]-='a'-1;    fr(i,1,m)        s2[i]-='a'-1;    fr(i,1,n)        fr(j,1,m)            if(s1[i]==s2[j])            {                h[i][j]=h[i-1][j-1]+1;                f[i][j]=f[i-1][j-1];                if(h[i-1][j]==h[i][j])                    f[i][j]=(f[i][j]+f[i-1][j])%mod;                if(h[i][j-1]==h[i][j])                    f[i][j]=(f[i][j]+f[i][j-1])%mod;            }            else            {                h[i][j]=max(h[i-1][j],h[i][j-1]);                   if(h[i-1][j]==h[i][j])                    f[i][j]=(f[i][j]+f[i-1][j])%mod;                if(h[i][j-1]==h[i][j])                    f[i][j]=(f[i][j]+f[i][j-1])%mod;                if(h[i-1][j-1]==h[i][j])                    f[i][j]=(f[i][j]-f[i-1][j-1]+mod)%mod;            }    printf("%d\n%d\n",h[n][m],f[n][m]);    return 0;}

hn,m 表示LCS长度

fn,m 表示LCS个数

我们可以得出

hi,j=hi1,j1+1max{hi1,jhi,j1s1i=s2js1is2j

fi,j 有些复杂,需要考虑许多情况:

我们先设一个函数 p(...)={10...true...false

fi,j={fi1,j1+p(hi1,j=hi,j)×fi1,j+p(hi,j1=hi,j)×fi,j1p(hi1,j=hi,j)×fi1,j+p(hi,j1=hi,j)×fi,j1p(hi1,j1=hi,j)×fi1,j1s1i=s2js1is2j

反正我是觉得没看代码直观。

至于这些怎么推出来的,应该是只有最后一条有疑问,反正减就是去重,可以参考NOIP2016Day2T1

原创粉丝点击