zoukankan      html  css  js  c++  java
  • 2020杭电多校 8K / HDU 6865

    HDU 6865 - Kidnapper's Matching Problem


    题意

    给定(n,m,k(mleq n)),给定长度为(n)的数组({a}),长度为(m)的数组({b}),长度为(k)的集合({S})

    定义(2_⊕^S)({S})任意子集异或和(xor_sum)的可能结果所形成的新集合

    定义两等长集合({x},{y})(matches)函数

    该函数会遍历判断(x_i xor y_i in 2_⊕^S)

    如果对于所有的(i(ileq|x|,|y|))(x_i xor y_i in 2_⊕^S)均成立,则(matches)返回(1),否则返回(0)

    问下式的值

    [sum_{i=1}^{n-m+1}[(a_i,a_{i+1},dots ,a_{i+m-1}) matches b]cdot2^{i-1} mod (10^9+7) ]


    限制

    (1leq Tleq 2cdot10^4)

    (1leq nleq2cdot10^5, 1leq mleq min(n, 5cdot10^4), 1leq kleq100)

    (0leq a_i,b_i,S_ilt2^{30})

    (sum nleq1.2cdot10^6, sum mleq3cdot10^5, sum kleq 6cdot10^5)




    思路

    先求出({S})的线性基(bs)

    (下面是官方题解的内容)


    结论:假设(x,y)消去线性基(bs)中的位后得到的数分别位(x',y'),那么下列关系式成立

    [x⊕yin 2_⊕^S iff x'=y' ]

    证明:

    充分性:根据线性基的性质,(x⊕y)必然能由(x'⊕y')再异或上线性基(bs)内某些数得到,所以在(x'=y')(x⊕yin 2_⊕^S)

    必要性:反证,因为(x',y')不包含线性基(bs)中的位(对应的位被消去),所以(x'⊕y')也不会包含(bs)中的位。又因为(x' eq y'),所以(x'⊕y' eq0),则(x'⊕y')一定包含无法用(bs)来表示的位,故(x'⊕y' otin 2_⊕^S)


    也确实只要有了这个结论,让({a})({b})中所有元素全部消去线性基(bs)中的位后,本题便变成了一道快速匹配模板题

    由于(ngeq m),且答案是根据([Sub(a) matches b])来计算的,故选择({a})作为主串,选择({b})作为模式串,套KMP即可

    主要注意对于题目公式中的(i=1),实际上在KMP中主串光标应该是位于(i=m)位置才对

    所以如果在主串第(p)个位置匹配成功,实际上应该加上(2^{p-m+1})

    由于按照顺序来匹配,(2^n)通过递推即可,其余的注意下细节就可以了




    代码

    (826ms/2000ms)

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    
    int n,m,k,a[200050],b[200050],S[111];
    int Next[200050];
    
    struct LinearBase
    {
        int v[35];
        void init()
        {
            memset(v,0,sizeof v);
        }
        void insert(int x)
        {
            for(int i=30;i>=0;i--)
                if(x>>i&1)
                {
                    if(v[i])
                        x^=v[i];
                    else
                    {
                        v[i]=x; 
                        break;
                    }
                }
        }
        int solve(int x)
        {
            for(int i=30;i>=0;i--)
                if(x>>i&1)
                    x^=v[i];
            return x;
        }
    }bs;
    
    void getNext()
    {
        Next[1]=0;
        for(int i=2,j=0;i<=m;i++)
        {
            while(j>0&&b[j+1]!=b[i])
                j=Next[j];
            if(b[j+1]==b[i])
                j++;
            Next[i]=j;
        }
    }
    
    void KMP()
    {
        int n2=1,ans=0;
        for(int i=1,j=0;i<=n;i++)
        {
            while(j>0&&b[j+1]!=a[i])
                j=Next[j];
            if(b[j+1]==a[i])
                j++;
            if(j==m)
            {
                ans=(ans+n2)%mod;
                j=Next[j];
            }
            if(i>=m)
                n2=(2LL*n2)%mod;
        }
        printf("%d
    ",ans);
    }
    
    void solve()
    {
        scanf("%d%d%d",&n,&m,&k);
        bs.init();
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=m;i++)
            scanf("%d",&b[i]);
        for(int i=1;i<=k;i++)
        {
            scanf("%d",&S[i]);
            bs.insert(S[i]);
        }
        for(int i=1;i<=n;i++)
            a[i]=bs.solve(a[i]);
        for(int i=1;i<=m;i++)
            b[i]=bs.solve(b[i]);
        getNext();
        KMP();
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
            solve();
        return 0;
    }
    

  • 相关阅读:
    Ueeidor 使用
    springMvc 拦截器
    redis 设置密码
    freemarker 定义公共header
    freemarker macro 使用
    freemarker ! 用法
    Android 远程连接数据库。。。。。
    Android Studio 配置
    Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
    表单,table的css
  • 原文地址:https://www.cnblogs.com/stelayuri/p/13498409.html
Copyright © 2011-2022 走看看