HDU6865 杭电多校8 1011-Kidnapper's Matching Problem (线性基+KMP)

HDU6865 杭电多校8 1011-Kidnapper's Matching Problem (线性基+KMP)

题意:

题意就是计算这个式子,[condition] 当\(a_{i} ... a_{i+m-1}​\) 与b数组满足匹配关系时为1。具体匹配关系指\(a_{i} \oplus b_{i} \in 2^{S}_{⊕}​\) 。其中 S 为输入的一组数,$ 2^{S}_{⊕}​$ 表示S数组所有任意子集的异或和结果的集合。

题解:

这里先放题解原文:

具体就是先用 S 数组计算其线性基,得到$ 2^{S}_{⊕}$ 。 然后按题解的结论把a[], b[]数组中的数去掉线性基中有的位得到 \(a`[\ ] ,b`[\ ]\)。然后找能够按题意匹配的位置 i ,当然按照题解结论,对匹配的那一段有 \(a`[i] = b`[i]\) 。 所以直接用KMP去处理就好了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i)
#define per(i, a, n) for(int i = n; i >= a; -- i)
typedef long long ll;
const int N = 2e6 + 105;
const int mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const ll INF = 1e18;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
//

const int maxbit = 62;		//maxbit不能太大

struct L_B{
	ll lba[maxbit], p[maxbit];
	int cnt;
	L_B(){
        memset(lba, 0, sizeof(lba));
        memset(p, 0, sizeof(p));
        cnt = 0;
    }
    
	void Insert(ll val){		//插入
        for(int i = maxbit - 1; i >= 0; -- i)
            if(val & (1ll << i)){
                if(!lba[i]){
                    lba[i] = val;
                    break;
                }
                val ^= lba[i];
            }
    }
};
// --------------线性基模板



int T, n, m, k;
ll a[N], b[N];
int nxt[N];
int vis[N];

void get_next()
{
    int i = 1, j = 0;
    nxt[1] = 0;
    while(i <= m){
        if(j == 0 || b[i] == b[j]){
            i ++, j ++, nxt[i] = j;
        }
        else j = nxt[j];
    }
}

void KMP()
{
    get_next();
    int i = 0, j = 0;
    while(i <= n && j <= m){
        if(j == 0 || a[i] == b[j]) i++, j++;
        else j = nxt[j];
        
        if(j == m + 1){
            vis[i - m] = 1;
            j = nxt[j];
        }
    }
}

void init(){
    for(int i = 0; i <= n; ++ i){
        nxt[i] = 0; vis[i] = 0;
    }
}

int main()
{
    scanf("%d",&T);
    while(T --){
        L_B lb;
        scanf("%d%d%d",&n,&m,&k);
        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){
            ll x; scanf("%lld",&x);
            lb.Insert(x);
        }
        for(int i = 1; i <= n; ++ i){
            for(int j = maxbit - 1; j >= 0; -- j){
                if(a[i] & (1 << j)){
                    a[i] ^= lb.lba[j];
                }
            }
        }
        for(int i = 1; i <= m; ++ i){
            for(int j = maxbit - 1; j >= 0; -- j){
                if(b[i] & (1 << j)){
                    b[i] ^= lb.lba[j];
                }
            }
        }

        init(); KMP();
        ll res = 0, temp = 1;
        for(int i = 1; i <= n - m + 1; ++ i){
            if(vis[i]) res = (res + temp) % mod;
            temp = temp * 2ll % mod;
        }
        printf("%lld\n",res);
    }
    return 0;
}

posted @ 2020-08-13 20:43  A_sc  阅读(300)  评论(0编辑  收藏  举报