zoukankan      html  css  js  c++  java
  • luogu4608 [FJOI2016]所有公共子序列问题

    题目描述:

    luogu

    loj

    题解:

    序列自动机(?)+高精+普及dp。

    这个是猫老师的序列自动机(字符串从1开始):

    void sol(char *s,int n,int t[N][53])
    {
        memset(t[n],-1,sizeof(t[n]));
        for(int i=n-1;i>=0;i--)
        {
            memcpy(t[i],t[i+1],sizeof(t[i]));
            t[i][ci(s[i+1])] = i+1;
        }
    }
    序列自动机

    $t$数组记录在位置$i$的后面加字符$j$能到达的最左边的位置。

    对于这道题,直接对两个串构造序列自动机,然后爆搜即可。

    $k=1$没啥好说的,$k=0$高精压18位。

    时间复杂度$O(n^2)$。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 3020;
    const ll M = 1000000000000000000ll;
    struct bignum
    {
        ll a[10];//8
        int len;
        void operator += (const bignum&x)
        {
            int mx = max(len,x.len);
            for(int i=0;i<mx;i++)
            {
                a[i]+=x.a[i];
                if(a[i]>=M)a[i+1]+=a[i]/M,a[i]%=M;
            }
            while(a[len])len++;
        }
        void operator += (const ll&x)
        {
            a[0]+=x;
            for(int i=0;a[i]>=M;i++)a[i+1]+=a[i]/M,a[i]%=M;
            while(a[len])len++;
        }
        void write()
        {
            if(!len){puts("0");return ;}
            printf("%lld",a[len-1]);
            for(int i=len-2;i>=0;i--)
                printf("%018lld",a[i]);
            puts("");
        }
    }dp[2500050];
    int n,m,k,t1[N][53],t2[N][53],id[N][N],tot=0,ans=0;
    char s1[N],s2[N];
    int ci(char ch)
    {
        if(ch>='A'&&ch<='Z')return ch-'A';
        return ch-'a'+26;
    }
    char ic(int i)
    {
        if(i<26)return 'A'+i;
        return 'a'+i-26;
    }
    void sol(char *s,int n,int t[N][53])
    {
        memset(t[n],-1,sizeof(t[n]));
        for(int i=n-1;i>=0;i--)
        {
            memcpy(t[i],t[i+1],sizeof(t[i]));
            t[i][ci(s[i+1])] = i+1;
        }
    }
    int tl;
    char now[N];
    void dfs1(int a,int b)
    {
        for(int i=1;i<=tl;i++)
            putchar(now[i]);
        putchar('
    ');
        ans++;
        for(int i=0;i<52;i++)if(~t1[a][i]&&~t2[b][i])
        {
            now[++tl] = ic(i);
            dfs1(t1[a][i],t2[b][i]);
            tl--;
        }
    }
    void dfs2(int a,int b)
    {
        if(id[a][b])return ;
        id[a][b]=++tot;
        dp[tot]+=1;
        for(int i=0;i<52;i++)if(~t1[a][i]&&~t2[b][i])
        {
            dfs2(t1[a][i],t2[b][i]);
            dp[id[a][b]]+=dp[id[t1[a][i]][t2[b][i]]];
        }
    }
    
    int main()
    {
    //    freopen("tt.in","r",stdin);
        scanf("%d%d%s%s%d",&m,&n,s1+1,s2+1,&k);
        sol(s1,m,t1),sol(s2,n,t2);
        if(k==1){dfs1(0,0);printf("%d
    ",ans);return 0;}
        dfs2(0,0);dp[id[0][0]].write();
        return 0;
    }
    View Code
  • 相关阅读:
    多项目共享配置文件
    C# 可选参数 命名参数
    委托初探
    未能解析引用的程序集……因为它对不在当前目标框架……
    web中的autocomplete
    web程序获取客户端MAC地址
    结合C#在MSSQL中定义和使用自定义类型
    winform中的AutoComplete自定义控件
    C#编写扩展存储过程
    eric windows下和linux的安装配置
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11080765.html
Copyright © 2011-2022 走看看