zoukankan      html  css  js  c++  java
  • 题解-CF961F k-substrings

    题面

    CF961F k-substrings

    给定字符串 (s),求每个左右端删除长度相等的子串的最长奇 border 长度。

    数据范围:(2le |S|le 10^6)


    题解

    其实是水题,vp 的时候比较懒散,写了个 z-function 发现不行就睡大觉去了,补题的时候画了幅图不能丢了只好写篇题解(完美的理由)。

    注意到一段长为 (n) 的字符串掐头去尾后黄色的这段仍然是新字符串的 border

    并且新字符串的 border 可以更大,所以两次答案满足 (a_0-2le a_1)

    如果从中间最小的子串往两边算,那么答案 (a) 每次最多增加 (2),可能减少。

    所以可以每次先给答案 (+2),再一直减到是 border 为止。

    判断 border 可以用 hash,时间复杂度 (Theta(n))


    代码

    //George1123
    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long i64;
    typedef unsigned int u32;
    typedef unsigned long long u64;
    typedef vector<int> vi;
    typedef pair<int,int> pii;
    
    #define x first
    #define y second
    #define sz(a) (int)((a).size())
    #define all(a) (a).begin(),(a).end()
    #define R(i,n) for(int i=0;i<(n);++i)
    #define L(i,n) for(int i=(n)-1;i>=0;--i)
    
    constexpr int inf32=0x3f3f3f3f;
    constexpr i64 inf64=0x3f3f3f3f3f3f3f3f;
    
    constexpr int mod=1000000007;
    
    struct mint{
        int x;
        mint(int x=0):x(x){}
        friend mint operator+
        (const mint a,const mint &b){
            int x=a.x+b.x;
            return mint(x>=mod?x-mod:x);
        }
        friend mint operator-
        (const mint a,const mint &b){
            int x=a.x-b.x;
            return mint(x<0?x+mod:x);
        }
        friend mint operator*
        (const mint a,const mint &b){
            return mint(1ll*a.x*b.x%mod);
        }
    };
    
    int mypow(int a,int x=mod-2,int res=1){
        for(;x;x>>=1,a=(mint(a)*a).x)
            if(x&1) res=(mint(res)*a).x;
    }
    
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0),cout.tie(0);
    
        int n;
        string s;
        cin>>n>>s;
    
        constexpr int B=3917;
        vi p(n+1),pw(n+1);
        pw[0]=1;
        R(i,n) pw[i+1]=(mint(pw[i])*B).x;
        R(i,n) p[i+1]=(mint(p[i])*B+s[i]).x;
        auto sec=[&](int l,int r){
            int res=(mint(p[r])-mint(p[l])*pw[r-l]).x;
            return res;
        };
    
        vi res(n+1>>1);
        if((~n&1)&&(s[n-1>>1]==s[
        n>>1])) res[n-1>>1]=1;
        else res[n-1>>1]=-1;
        L(i,n-1>>1){
            res[i]=res[i+1]+2;
            for(;res[i]>-1;res[i]-=2)
                if(sec(i,i+res[i])==sec(n-i-res[i],n-i))
                    break;
        }
        R(i,n+1>>1) cout<<res[i]<<' ';
        cout<<'
    ';
    
        return 0;
    }
    
    /* stuff you should look for
    	* int overflow, array bounds
    	* special cases (n=1?)
    	* do smth instead of nothing and stay organized
    	* WRITE STUFF DOWN
    	* DON'T GET STUCK ON ONE APPROACH
    */
    

    沉舟侧畔千帆过,病树前头万木春,退役了!

  • 相关阅读:
    Mybatis oracle多表联合查询分页数据重复的问题
    The Decade of Deep Learning
    D3S – A Discriminative Single Shot Segmentation Tracker
    Recent Advancements in NLP
    A list of datasets directly related to Music Information Retrieval Datasets
    Best Resources for Imbalanced Classification
    Attention-based Dropout Layer for Weakly Supervised Object Localization
    Learning a Discriminative Filter Bank within a CNN for Fine-grained Recognition
    Batch DropBlock Network for Person Re-identification and Beyond
    Cross-channel Communication Networks
  • 原文地址:https://www.cnblogs.com/George1123/p/14334397.html
Copyright © 2011-2022 走看看