zoukankan      html  css  js  c++  java
  • CF314B Sereja and Periods

    这里介绍两种做法,感觉都很巧妙。

    Solution 1

    观察题面,发现 (|a|,|c|leq 100) ,所以可以像 (KMP) 那样,造一个 (nxt) 数组,然后再弄一个 (cnt) 数组。

    其中 (cnt_i) 表示从 (c_i) 开始匹配,把 (a) 串扫一遍有几组匹配, (nxt_i) 表示 (c_i) 匹配完一个 (a) 到了 (c) 的哪一位。

    然后从 (1)(b) ,每次跳 (nxt)(ans+=cnt) 即可。

    时间复杂度: (O(len_acdot len_b)+O(b)=O(b))

    代码1

    #include<bits/stdc++.h>
    #define ll long long
    
    using namespace std;
    const int N=110;
    ll cnt[N],nxt[N],b,d,lena,lenc,ans;
    char a[N],c[N];
    
    int main(){
        scanf("%lld%lld%s%s",&b,&d,a,c);
        lena=strlen(a),lenc=strlen(c);
        for(int i=0,x;i<lenc;i++){
            x=i;
            for(int j=0;j<lena;j++)
                if(a[j]==c[x]){
                    x++;
                    if(x==lenc) cnt[i]++,x=0;
                }
            nxt[i]=x;
        }
        int pos=0;
        for(int i=1;i<=b;i++){
            ans+=cnt[pos];
            pos=nxt[pos];
        }
        printf("%lld
    ",ans/d);
        return 0;
    }
    

    Solution2

    我们用倍增的思想来做题。

    弄一个倍增数组 (go) ,拿 (pair) 储存。

    (go_{k,idx(i,j)}) 为从 (a) 的第 (i) 位, (c) 的第 (j) 位开始匹配,匹配 (c)(2^k) 位之后, (first) 表示此时两个串上的位置, (second) 为过了几个 (a) ,递推数组即可。

    二分匹配长度,求得答案。

    时间复杂度: (O(len_acdot len_blog(len_acdot b)))

    代码2

    #include<bits/stdc++.h>
    #define ll long long
    #define PII pair<int,ll>
    
    using namespace std;
    const int N=110,INF=0x3f3f3f3f;
    char a[N],c[N];
    ll lena,lenc,b,d;
    PII go[30][N*N];
    
    inline int idx(int i,int j){
        return i*lenc+j;
    }
    
    ll solve(int dis){
        int tmp=idx(0,0);
        ll res=0;
        for(int i=0;i<30;i++){
            if(dis>>i&1){
                res+=go[i][tmp].second;
                tmp=go[i][tmp].first;
            }
        }
        return res;
    }
    
    int main(){
        scanf("%lld%lld%s%s",&b,&d,a,c);
        lena=strlen(a);lenc=strlen(c);
        for(int i=0;i<lena;i++)
            for(int j=0;j<lenc;j++){
                int id=idx(i,j);
                go[0][id]=make_pair(id,INF);
                for(int k=0;k<lena;k++)
                    if(a[(i+k)%lena]==c[j]){
                        go[0][id]=make_pair(idx((i+k+1)%lena,(j+1)%lenc),(i==0)||((i+k)/lena));
                        break;
                    }
            }
        for(int i=1;i<30;i++)
            for(int j=0;j<lena*lenc;j++){
                int nxt=go[i-1][j].first;
                go[i][j]=make_pair(go[i-1][nxt].first,go[i-1][j].second+go[i-1][nxt].second);
            }
        ll l=0,r=INF;
        while(l<r){
            ll mid=(l+r+1)>>1;
            if(solve(mid)<=b) l=mid;
            else r=mid-1;
        }
        printf("%lld
    ",l/(lenc*d));
        return 0;
    }
    
  • 相关阅读:
    docker基础:docker网络模式
    WEB架构师成长之路之一-走正确的路(转载)
    DDD(领域驱动设计)
    C#泛型和泛型约束(转载)
    MES系统介绍
    vue中 computed和watch的一些简单理解(区别)(转载)
    sqlserver常用表值函数
    SQLServerAgent 当前未运行,因此无法将此操作通知它。
    浅谈敏捷开发(转载)
    认证、授权、鉴权和权限控制(转载)
  • 原文地址:https://www.cnblogs.com/jasony/p/13817567.html
Copyright © 2011-2022 走看看