• Rusty String


    题意:

    给定一个含有两种字符'V','K'以及?的字符串,问该串可能的循环节。

    解法:

    首先如果对于$d$,我们有不存在 $(j-i) | d$ 且 $S_i = 'V',  S_j = 'K'$ 的,那么 $d$ 为1循环节。

    这样考虑对于每一个 $d$ 求出 $j-i = d$ 的 $S_i = 'V',  S_j = 'K'$ 是否存在,然后 $O(nlogn)$ 筛一遍即可。

    求 $j - i = d$ 的有

    $$c_{n - i} = sum_{0 leq j leq i} { a(j) b(n-i+j-1) }$$

    $$c_{n - i} =  (reva otimes b)_{2n-i-1} =  sum_{0 leq t leq 2n-i-1}{ reva_t b_{2n-i-1-t} }$$

    标准卷积,DFT即可。

    #include <bits/stdc++.h>
    
    #define PI acos(-1)
    
    const int N = 500010;
    
    using namespace std;
    
    struct EX
    {
        double real,i;
        EX operator+(const EX tmp)const{return (EX){real+tmp.real, i+tmp.i};};
        EX operator-(const EX tmp)const{return (EX){real-tmp.real, i-tmp.i};};
        EX operator*(const EX tmp)const{return (EX){real*tmp.real - i*tmp.i, real*tmp.i + i*tmp.real};};
    };
    
    int R[N<<2];
    
    void DFT(EX a[],int n,int tp_k)
    {
        for(int i=0;i<n;i++) if(i<R[i]) swap(a[i],a[R[i]]);
        for(int d=1;d<n;d<<=1)
        {
            EX wn = (EX){cos(PI/d), sin(PI/d)*tp_k};
            for(int i=0;i<n;i += (d<<1))
            {
                EX wt = (EX){1,0};
                for(int k=0;k<d;k++, wt = wt*wn)
                {
                    EX A0 = a[i+k], A1 = wt * a[i+k+d];
                    a[i+k] = A0+A1;
                    a[i+k+d] = A0-A1;
                }
            }
        }
        if(tp_k==-1)
            for(int i=0;i<n;i++) a[i] = (EX){a[i].real/n, a[i].i/n};
    }
    
    EX A[N<<2],B[N<<2],C[N<<2];
    char S[N];
    int n;
    bool del[N],ans[N];
    
    void calc(char ch1,char ch2,int tot)
    {
        for(int i=0;i<tot;i++) A[i] = B[i] = (EX){0,0};
        for(int i=0;i<n;i++) if(S[i]==ch1) B[i] = (EX){1,0};
        for(int i=1;i<=n;i++) if(S[n-i]==ch2) A[i] = (EX){1,0};
        DFT(A,tot,1);
        DFT(B,tot,1);
        for(int i=0;i<tot;i++) C[i] = A[i]*B[i];
        DFT(C,tot,-1);
        for(int i=0;i<n;i++)
        {
            int tmp = (int)(C[2*n-i-1].real+0.5);
            if(tmp) del[i] = 1;
        }
    }
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            scanf("%d%s",&n,S);
            int L = 0,tot;
            while((1<<L)<n+n) L++;
            tot = (1<<L);
            for(int i=1;i<tot;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
            for(int i=0;i<n;i++) del[i] = 0, ans[i+1] = 0;
            calc('V','K',tot);
            calc('K','V',tot);
            for(int i=n-1;i>=0;i--) if(!del[i]) ans[n-i-1] = 1;
            ans[n] = 1;
            int cnt = 0;
            for(int i=1;i<=n;i++)
            {
                for(int j=i+i;j<=n;j+=i) ans[i] &= ans[j];
                if(ans[i]) cnt++;
            }
            printf("%d
    ",cnt);
            for(int i=1;i<=n;i++) if(ans[i]) printf("%d ",i);
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    重新整理 .net core 实践篇————配置系统之盟约[五]
    重新整理 .net core 实践篇————依赖注入应用之援军[四]
    重新整理 .net core 实践篇————依赖注入应用之生命法则[三]
    重新整理 .net core 实践篇————依赖注入应用[二]
    重新整理 .net core 实践篇————配置应用[一]
    spring cloud 学习笔记 客户端(本地)均衡负载(三)
    Leetcode之插入区间
    Leetcode之两棵二叉搜索树中的所有元素
    Leetcode之二叉树的层序遍历
    LeetCode之验证二叉搜索树
  • 原文地址:https://www.cnblogs.com/lawyer/p/7182032.html
Copyright © 2020-2023  润新知