zoukankan      html  css  js  c++  java
  • [BZOJ2085] [Poi2010]Hamsters

    [BZOJ2085] [Poi2010]Hamsters

    Description

    Tz养了一群仓鼠,他们都有英文小写的名字,现在Tz想用一个字母序列来表示他们的名字,只要他们的名字是字母序列中的一个子串就算,出现多次可以重复计算。现在Tz想好了要出现多少个名字,请你求出最短的字母序列的长度是多少。

    Input

    输入:第一行n(1<=n<=200)和m(1<=m<=10的9此方),n表示有多少个仓鼠,m表示Tz希望出现名字的次数,接下来n行,每行都是仓鼠的名字(中间没有空格)。

    Output

    输出:一行,最短的字母序列的长度。

    Sample Input

    4 5
    monika
    tomek
    szymon
    bernard

    Sample Output

    23

    试题分析

    显然两个字符串首尾相交需要重合才可以最小,那么我们可以预处理一下两个字符串有顺序连接的代价。
    然后我们就可以倍增转移。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
     
    using namespace std;
    #define LL long long
     
    inline LL read(){
        LL x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const LL INF = 1e18;
    const LL MAXN = 200010;
    const LL Mod = 98152501LL;
    const LL base = 131LL;
     
    vector<LL> vec[211][2]; string str[211]; LL N,M;
    LL Pw[MAXN+1];LL len[211];
    inline void Hash(LL x){
        LL las=0; for(LL i=0;i<len[x];i++)
            vec[x][0].push_back(las=(las*base%Mod+(str[x][i]-'a'))%Mod);
        las=0; for(LL i=len[x]-1;i>=0;i--)
            vec[x][1].push_back(las=(las%Mod+(str[x][i]-'a')*Pw[len[x]-i-1])%Mod);
        return ;
    } LL to[211][211],f[211][211],g[211][211];
     
     
    inline void Solve(LL x){
        if(x==1){
            for(LL i=1;i<=N;i++){
                for(LL j=1;j<=N;j++)
                    f[i][j]=to[i][j];
            } return ;
        } Solve(x>>1);
        for(LL i=1;i<=N;i++){
            for(LL j=1;j<=N;j++) g[i][j]=f[i][j];
        } memset(f,0x3f,sizeof(f));
        for(LL i=1;i<=N;i++){
            for(LL j=1;j<=N;j++)
                for(LL k=1;k<=N;k++)
                    f[j][k]=min(g[j][i]+g[i][k],f[j][k]);
        } if(x&1){
            for(LL i=1;i<=N;i++){
                for(LL j=1;j<=N;j++) g[i][j]=f[i][j];
            } memset(f,0x3f,sizeof(f));
            for(LL i=1;i<=N;i++){
                for(LL j=1;j<=N;j++){
                    for(LL k=1;k<=N;k++)
                        f[j][k]=min(f[j][k],g[j][i]+to[i][k]);
                }
            }
        } return ;
    }
     
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        N=read(),M=read(); Pw[0]=1; for(LL i=1;i<=MAXN;i++) Pw[i]=Pw[i-1]*base%Mod; LL ret=INF;
        for(LL i=1;i<=N;i++) cin>>str[i],len[i]=str[i].length(),Hash(i),ret=min(ret,len[i]);
        if(M==1){printf("%lld
    ",ret); return 0;}
        for(LL i=1;i<=N;i++){
            for(LL j=1;j<=N;j++){
                LL fg=0; //to[i][j]=len[i]; if(i==j) continue;
                for(LL k=(i==j?len[i]-2:min(len[i]-1,len[j]-1));k>=0;k--){
                    if(vec[i][1][k]==vec[j][0][k]){fg=k+1; break;}
                } to[i][j]=len[j]-fg; 
            }
        } Solve(M-1); 
        LL ans=INF;
        for(LL i=1;i<=N;i++){
            for(LL j=1;j<=N;j++)
                ans=min(ans,len[i]+f[i][j]);
        } printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    分布式事务slides
    为什么jdk中把String类设计成final
    Struts 体系结构与工作原理 图
    在指定路径或者是文件名查找指定的字符串
    Apache Avro 与 Thrift 比较
    SSL请求trustStore的两种注册方式
    java中的split使用的是正则表达式
    所有ghost操作系统大全
    Tomcat帮助文档翻译 未完成
    ORACLE基本配置
  • 原文地址:https://www.cnblogs.com/wxjor/p/9515817.html
Copyright © 2011-2022 走看看