zoukankan      html  css  js  c++  java
  • Count The Repetitions

    Count The Repetitions

    定义(conn(s,n))为字符串s重复n次形成的新字符串,定义字符串a能被字符串b生成,当且仅当a是b的子串,现在给出s1,n1,s2,n2,求最大的m使(conn(conn(s2,n2),m))能被(conn(s1,n1))生成,(s_1)(s_2) 长度不超过100,(n_1)(n_2) 不大于 (10^6)

    首先(conn(conn(s2,n2),m)=conn(s2,n2 imes m)),于是可以令(m'=n2 imes m),现在只要求出最大的m即可。

    注意到字符串为循环节,循环节,模数是倍增的大展身手之处,于是我们可以设(f[i][j])表示s1中的第i个位置开始至少要多少个字符,形成(2^j)个s2,当j=0,可以(n^2)枚举,注意判断无解的情况,而且如果一个地方有解的话,每个地方都会有数值。

    因此不难有

    (f[i][j]=f[i][j-1]+f[i+f[i][j-1]][j-1])

    维护好了倍增数组,接下来二进制拆分考虑问题,s1存在范围,故从大的次幂到小枚举,并保证不超过(s1.size() imes n1)的前提下,尽可能让m大,输出(n/n2)即可。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    #define ll long long
    using namespace std;
    string s1,s2;
    int len1,len2;
    ll dp[150][28];
    il void work(int,int);
    int main(){
        int n1,n2;
        while(cin>>s2>>n2>>s1>>n1)work(n1,n2);
        return 0;
    }
    il void work(int n1,int n2){
        memset(dp,0,sizeof(dp));
        int li((ll)n1*s1.size()),m(0);
        for(int i(0),j,k,tot;i<s1.size();++i)
            for(j=0,k=i;j<s2.size();++j){tot=0;
                while(s1[k]!=s2[j]&&tot<=s1.size())(++k)%=s1.size(),++tot;
                if(tot>s1.size())return (void)(puts("0"));
                dp[i][0]+=tot+1,(++k)%=s1.size();
            }
        for(int j(1),i;j<28;++j)
            for(i=0;i<s1.size();++i)
                dp[i][j]=dp[i][j-1]+dp[(i+dp[i][j-1])%s1.size()][j-1];
        for(int i(27),j(0);i>=0;--i)
            if(dp[j][i]<=li)
                li-=dp[j][i],m+=1<<i,(j+=dp[j][i])%=s1.size();
        printf("%d
    ",m/n2);
    }
    
  • 相关阅读:
    Top WAF
    Access-Control-Allow-Origin与跨域
    SQLlite
    SHell命令总结
    yum仅下载RPM包不安装
    Taglib
    JFinal
    Eclipse maven git
    maven jetty plugin
    wechat
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10954675.html
Copyright © 2011-2022 走看看