• $[NOIp2015]$ 子串 $dp$


    (Sol)

    不知道为啥看起来就很(dp)的亚子.我们关心的只有(A)串当前用到哪一个,(B)串已经匹配到哪个位置,已经匹配的被分成了多少段.所以设(f_{i,j,k,0/1})表示(A)串用到第(i)个,(B)串已经匹配到第(j)个,分成了(k)段,最后一段是否被断开.

    瞎转移一波(这里就不详细讲了,看代码也很容易懂)就获得了(90pts)的好成绩.还有(10pts)呢?数组开不下吖(QwQ).我开始居然没想到滚动数组,还乱搞了一波(map),发现(f_{i,j,k,0/1})一定是转移到(f_{i+1,j',k',0/1}),所以可以滚动第一维,要注意在循环开始的时候清空一维数组.

    (Code)

    #include<bits/stdc++.h>
    #define il inline
    #define Ri register int
    #define go(i,a,b) for(Ri i=a;i<=b;++i)
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    il int read()
    {
        Ri x=0,y=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        return x*y;
    }
    const int N=1005,mod=1000000007;
    int n,m,kk,as,f[2][205][205][2];char s1[N],s2[N];
    il void inc(Ri &x,Ri y){x+=y;if(x>=mod)x-=mod;}
    int main()
    {
        n=read(),m=read(),kk=read();
        scanf("%s",s1+1);scanf("%s",s2+1);
        f[0][0][0][0]=1;
        go(ii,0,n)
        {
    	    Ri i=ii&1;
    	    mem(f[i^1],0);
    	    go(j,0,min(m,ii))
    	    go(k,0,kk)
    	    go(g,0,1)
                {
    	        if(!f[i][j][k][g])continue;
    	        inc(f[i^1][j][k][0],f[i][j][k][g]);
    	        if(s1[ii+1]==s2[j+1])
    	        {
    		    inc(f[i^1][j+1][k+1][1],f[i][j][k][g]);
    		    if(g)inc(f[i^1][j+1][k][1],f[i][j][k][g]);
    	        }
    	    }
    	    inc(as,f[i][m][kk][1]);
        }
        printf("%d
    ",as);
        return 0;
    }
    
    
  • 相关阅读:
    192021
    191020
    magento注册
    magento登陆
    把PHP的数组变成带单引号的字符串
    magento直接操作数据库
    兼容各大浏览器的event获取
    手动修改magento域名
    微信支付中的jsapi返回提示信息
    CentOS 下安装xdebug
  • 原文地址:https://www.cnblogs.com/forward777/p/11747207.html
Copyright © 2020-2023  润新知