• 安徽师大附中%你赛day6 T3 Hamsters [POI2010]CHO-Hamsters 解题报告


    [POI2010]CHO-Hamsters

    题意:

    给出n个互不包含的字符串,要求你求出一个最短的字符串S,使得这n个字符串在S中总共至少出现m次,问S最短是多少?

    范围:

    (1 le n le 200,1 le m le 10^9),(sum_S le 100000)


    图论模型,矩阵乘法优化floyd

    首先虚点连字符串,边权为长度,然后字符串相互连接,边权为后者长度-最长公共部分

    前后匹配的方法比较多,hash,kmp,AC自动机都行

    然后很容易找到一个floyd的方法

    我们利用矩阵快速幂进行优化就行了


    Code:

    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    #define ll long long
    ll min(ll x,ll y){return x<y?x:y;}
    const int N=202;
    int n,m;
    struct matrix
    {
        ll dx[N][N];
        matrix()
        {
            memset(dx,0x3f,sizeof(dx));
        }
        matrix friend operator *(matrix n1,matrix n2)
        {
            matrix n3;
            for(int k=0;k<=n;k++)
                for(int i=0;i<=n;i++)
                    for(int j=0;j<=n;j++)
                        n3.dx[i][j]=min(n3.dx[i][j],n1.dx[i][k]+n2.dx[k][j]);
            return n3;
        }
    }x,f;
    char name[100010];
    const ll base=26,mod=19260817;
    ll g[N][N],pow[100010];
    vector <ll> has[N];
    ll get_hash(int id,int l,int r)
    {
        return ((has[id][r]-has[id][l-1]*pow[r+1-l])%mod+mod)%mod;
    }
    ll cal(int i,int j)
    {
        int l1=x.dx[0][i],l2=x.dx[0][j];
        for(int k=min(l1,l2)-1;k;k--)
            if(get_hash(i,l1-k+1,l1)==get_hash(j,1,k)) return k;
        return 0;
    }
    void init()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",name+1);
            int len=strlen(name+1);
            x.dx[0][i]=len;
            has[i].push_back(0);
            for(int j=1;j<=len;j++)
                has[i].push_back(has[i][j-1]*base%mod+name[j]-'a');
        }
        pow[0]=1;
        for(int i=1;i<=100000;i++)
            pow[i]=pow[i-1]*base%mod;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                x.dx[i][j]=x.dx[0][j]-cal(i,j);
    }
    void work()
    {
        --m;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                f.dx[i][j]=x.dx[i][j];
        while(m)
        {
            if(m&1) f=f*x;
            x=x*x;
            m>>=1;
        }
        ll ans=0x7fffffffffffffffll;
        for(int i=1;i<=n;i++)
            ans=min(ans,f.dx[0][i]);
        printf("%lld
    ",ans);
    }
    int main()
    {
        init();
        work();
        return 0;
    }
    
    

    2018.8.18

  • 相关阅读:
    AmazonS3 替换HDFS 方案
    SQL Server 内存管理
    SQL Server I/O 问题的诊断分析
    共享内存 设计原理-shm
    机器学习经典算法笔记-Support Vector Machine SVM
    ACGAN 论文笔记
    CGAN 论文笔记
    《Image Generation with PixelCNN Decoders》论文笔记
    《Iterative-GAN》的算法伪代码整理
    《Deep Learning Face Attributes in the Wild》论文笔记
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9498594.html
Copyright © 2020-2023  润新知