zoukankan      html  css  js  c++  java
  • Codeforces 526D Om Nom and Necklace (KMP)

    http://codeforces.com/problemset/problem/526/D

    题意

    给定一个串 T,对它的每一个前缀能否写成 A+B+A+B+...+B+A+B+A+B+...+B+A 的形式(k +1个 Ak 个 B,均可为空串)

    分析

    官方题解

    对于前缀P,我们可以把它拆成P=SSSS…SSSST,其中T是S的前缀。显然可以用KMP算法,时间复杂度是O(n)。

    当T=S:P=SSS…S。假设S出现了R次。如果转换为ABABAB…ABABA的形式,A和B是由几个S组成,而且最后的A一定是P的一个后缀。由贪心算法,A的长度尽量小,所以A中S出现R mod Q次。B中S出现R/Q-R mod Q次。因为只需判断R/Q-R mod Q>=0即可

    当T!=S:由于上一种方法类似,A可以是SSS…ST,因为它的长度尽量小,所以我们只需判断是否R/Q-R mod Q>0。

    那为什么A中有R mod Q个S,B中有R/Q-R mod Q 个S?因为要将字符串P=SSSSSSS变成ABABABABA的形式,可以看成是Q份AB和一份A结合,那么每份AB就有R/Q个S,所以剩下的R%Q就是A的S,于是B就是R/Q-R mod Q了。

    当T=S时,B可以为空串,也就是B的长度可以为0,于是取等号。当T!=S时,反之。

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    #include<set>
    #define rep(i,e) for(int i=0;i<(e);i++)
    #define rep1(i,e) for(int i=1;i<=(e);i++)
    #define repx(i,x,e) for(int i=(x);i<=(e);i++)
    #define X first
    #define Y second
    #define PB push_back
    #define MP make_pair
    #define mset(var,val) memset(var,val,sizeof(var))
    #define scd(a) scanf("%d",&a)
    #define scdd(a,b) scanf("%d%d",&a,&b)
    #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define pd(a) printf("%d
    ",a)
    #define scl(a) scanf("%lld",&a)
    #define scll(a,b) scanf("%lld%lld",&a,&b)
    #define sclll(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
    #define IOS ios::sync_with_stdio(false);cin.tie(0)
    
    using namespace std;
    typedef long long ll;
    template <class T>
    void test(T a){cout<<a<<endl;}
    template <class T,class T2>
    void test(T a,T2 b){cout<<a<<" "<<b<<endl;}
    template <class T,class T2,class T3>
    void test(T a,T2 b,T3 c){cout<<a<<" "<<b<<" "<<c<<endl;}
    const int inf = 0x3f3f3f3f;
    const ll INF = 0x3f3f3f3f3f3f3f3fll;
    const ll mod = 200907;
    int T;
    void testcase(){
        printf("Case #%d: ",++T);
    }
    const int MAXN = 1e6+5;
    const int MAXM = 30;
    int n,k;
    char s[MAXN];
    int Next[MAXN];
    
    void getNext(){
        int i,j;
        j=Next[0]=-1;
        i=0;
        while(i<n){
            while(-1!=j&&s[i]!=s[j]) j=Next[j];
            Next[++i]=++j;
        }
    }
    int check(int i){
        int d=i-Next[i]; //最小循环节
        int cnt = i/d; //循环节次数
        if(i%d==0){ //被整除
            return cnt/k-cnt%k>=0;  //
        }else return cnt/k-cnt%k>0;
    
    }
    int main() {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif // LOCAL
        scdd(n,k);
        scanf("%s",s);
        mset(Next,0);
        getNext();
        for(int i=1;i<=n;i++){
            printf("%d",check(i));
        }
    //    for(int i=0;i<=1+n;i++) printf("%d ",Next[i]);
        return 0;
    }
  • 相关阅读:
    Spring事务原理分析-部分二
    Spring事务原理分析-部分一
    Spring 通读官方文档
    Spring IOC 源码解析
    SpringAOP原理分析
    Docker学习笔记
    TCP、UDP和HTTP关系
    洛谷P3312
    洛谷P3327
    BZOJ3073
  • 原文地址:https://www.cnblogs.com/fht-litost/p/9296893.html
Copyright © 2011-2022 走看看