zoukankan      html  css  js  c++  java
  • $[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;
    }
    
    
  • 相关阅读:
    BZOJ5212 ZJOI2018历史(LCT)
    BZOJ5127 数据校验
    253. Meeting Rooms II
    311. Sparse Matrix Multiplication
    254. Factor Combinations
    250. Count Univalue Subtrees
    259. 3Sum Smaller
    156. Binary Tree Upside Down
    360. Sort Transformed Array
    348. Design Tic-Tac-Toe
  • 原文地址:https://www.cnblogs.com/forward777/p/11747207.html
Copyright © 2011-2022 走看看