• P2679 子串


    传送门

    思路:

      设 f [ i ][ j ][ k ][ 0/1 ] 表示 A 串匹配到第 i 个,B 串匹配到第 j 个,已经匹配到第 k 段,0: A[ i ] 与 B[ j ] 不匹配, 1: A[ i ] 与 B[ j ] 匹配。

      状态转移可分为 A[ i ] 与 B[ j ] 匹配和不匹配两种状态:

      ① 若不匹配, f [ i ][ j ][ k ][ 0 ] = f [ i-1 ][ j ][ k ][ 0 ] + f [ i-1 ][ j ][ k ][ 1 ] 。

      ② 匹配,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 ] 。

      如果直接将 f 数组开到 4 维,128M 的空间明显不够。

      考虑到每次的状态转移只和前一次的状态有关,所以可以将 f 的第一维用二进制滚动 。

    Code:

    70 Points:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<deque>
    #include<map>
    #include<set>
    using namespace std;
    #define lck_max(a,b) ((a)>(b)?(a):(b))
    #define lck_min(a,b) ((a)<(b)?(a):(b))
    typedef long long LL;
    const int maxn=101;
    const int mod=1e9+7;
    LL n,m,K,ans,f[(maxn<<1)+(maxn<<3)][maxn<<1][maxn<<1][2];
    char s1[(maxn<<1)+(maxn<<3)],s2[maxn<<1];
    inline LL read()
    {
        LL kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(!(ls^45))
                kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return xs*kr;
    }
    inline void out(LL xs)
    {
        if(!xs) {putchar(48); return;}
        if(xs<0) putchar('-'),xs=-xs;
        int kr[57],ls=0;
        while(xs) kr[++ls]=xs%10,xs/=10;
        while(ls) putchar(kr[ls]+48),ls--;
    }
    int main()
    {
        n=read();m=read();K=read();
        scanf("%s",s1+1);scanf("%s",s2+1);
        f[0][0][0][0]=1;
        for(LL i=1;i<=n;i++)
        {
            f[i][0][0][0]=1;
            for(LL j=1;j<=m;j++)
            {
                for(LL k=1;k<=K;k++)
                {
                    f[i][j][k][0]=(f[i-1][j][k][0]+f[i-1][j][k][1])%mod;
                    if(s1[i]==s2[j])
                        f[i][j][k][1]=(f[i-1][j-1][k][1]+f[i-1][j-1][k-1][0]+f[i-1][j-1][k-1][1])%mod;
                }
            }
        }
        out((f[n][m][K][0]+f[n][m][K][1])%mod);
    return 0;
    }

    100 Points:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<deque>
    #include<map>
    #include<set>
    using namespace std;
    #define lck_max(a,b) ((a)>(b)?(a):(b))
    #define lck_min(a,b) ((a)<(b)?(a):(b))
    typedef long long LL;
    const int maxn=101;
    const int mod=1e9+7;
    bool pos=true;
    LL n,m,K,ans,f[2][maxn<<1][maxn<<1][2];
    char s1[(maxn<<1)+(maxn<<3)],s2[maxn<<1];
    inline LL read()
    {
        LL kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(!(ls^45))
                kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return xs*kr;
    }
    inline void out(LL xs)
    {
        if(!xs) {putchar(48); return;}
        if(xs<0) putchar('-'),xs=-xs;
        int kr[57],ls=0;
        while(xs) kr[++ls]=xs%10,xs/=10;
        while(ls) putchar(kr[ls]+48),ls--;
    }
    int main()
    {
        n=read();m=read();K=read();
        scanf("%s",s1+1);scanf("%s",s2+1);
        f[0][0][0][0]=1;f[1][0][0][0]=1;
        for(LL i=1;i<=n;i++,pos^=1)
        {
            for(LL j=1;j<=m;j++)
            {
                for(LL k=1;k<=K;k++)
                {
                    f[pos][j][k][0]=(f[pos^1][j][k][0]+f[pos^1][j][k][1])%mod;
                    if(s1[i]==s2[j])
                        f[pos][j][k][1]=(f[pos^1][j-1][k][1]+f[pos^1][j-1][k-1][0]+f[pos^1][j-1][k-1][1])%mod;
                    else f[pos][j][k][1]=0;
                }
            }
        }
        out((f[n&1][m][K][0]+f[n&1][m][K][1])%mod);
    return 0;
    }
  • 相关阅读:
    [极客大挑战 2019]BuyFlag
    [极客大挑战 2019]BabySQL
    [网鼎杯 2018]Fakebook
    C语言学习笔记_内存数据和字符串
    剑指OFFER_数据流中的中位数
    剑指OFFER_滑动窗口的最大值
    剑指OFFER_矩阵中的路径
    C语言学习笔记_指针相关知识
    剑指OFFER_机器人的运动范围
    剑指OFFER_剪绳子
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9857652.html
Copyright © 2020-2023  润新知