hdu 6865

处理s的线性基。
ab数组异或掉s线性基中部分。
变为ab数组的kmp。

#include
#include
using namespace std;
#define mp make_pair
#define pb push_back
#define mt(a,b) memset(a,b,sizeof(a))
#define zero(x) (((x)>0?(x):-(x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const double pi = 3.14159265;
const double eps = 0.000001;
const ll Mod = 1e9 + 7;
//const ll mod = 998244353;
const ll mod = 1e9 + 7;
const int maxn = 2e5 + 7;


#define N 60
struct Basis{
     
    int n;
    ll r[N+1]; //线性基
    ll f[N+1];
    ll tot;
    bool ins(ll x){
     
        for (int i=N;i>=0;i--)
            if (x>>i){
     
                if (!r[i]) {
     
                tot++;r[i]=x;return 1;}
                x^=r[i];
                if (!x) return 0;
            }
        return 0;
    }
    void ins2(ll x){
     
        ll tmp=x;
        for (int i=N;i>=0;i--)
            if (x>>i){
     
                if (!r[i]) {
     f[i]=tmp;r[i]=x;return;}
                x^=r[i]; tmp^=f[i];
                if (!x) return;
            }
        return;
    }
    bool find(ll x){
     
        for (int i=N;i>=0;i--)
            if (x>>i){
     
                if (!r[i]) return 0;
                x^=r[i];
            }
        return x==0;
    }
    ll cal(ll x){
     
        ll ret=0;
        for (int i=N;i>=0;i--){
     
            if (x>>i){
     
                ret^=f[i];
                x^=r[i];
            }
        }
        return ret;
    }

//求最大异或和
	ll get_max(){
     
		ll ans=0;
		for(int i=N;i>=0;i--){
     
			if((ans^r[i])>ans){
     
				ans^=r[i];
			}
		}
		return ans;
	}

//求第k小异或和,n为原序列元素个数,tot为线性基元素个数
    void work(){
     
		for(int i=1;i<=N;i++){
     
			for(int j=1;j<=i;j++){
     
				if(r[i] & (1ll<<(j-1))){
     
					r[i]^=r[j-1];
				}
			}
		}
	}
	ll get (ll x)
	{
     
	    for (int i=N;i>0;i--){
     
            if(x & (1ll<<(i-1))){
     
					x^=r[i-1];
				}
        }
        return x;
	}
	ll k_th(ll k){
     
		if(k==1 && tot<n) return 0;
		if(k+(tot==n)>(1ll<<tot)) return -1;
		if(tot<n) k--;
		ll ans=0;
		for(int i=0;i<=N;i++){
     
			if(r[i]){
     
				if(k%2) ans^=r[i];
				k/=2;
			}
		}
		return ans;
	}

    void print(){
     
        for (int i=0;i<=N;i++)cout<<r[i]<<' ';cout<<endl;
    }
    void clear(int n){
     
        for (int i=0;i<=N;i++) r[i]=f[i]=0;
        tot=0;
        this->n = n;
    }
    void clear(){
     
        for (int i=0;i<=N;i++) r[i]=f[i]=0;
        tot=0;
    }
}f;
Basis merge(Basis u, Basis v){
     
		Basis ret,tmp;
		ret.clear();
		tmp=u;
		for(int i=N;i>=0;i--){
     
			ll x=v.r[i];
			if(tmp.find(x)){
     
				ret.ins(x^tmp.cal(x));
			}
			else tmp.ins2(x);
		}
		return ret;
	}



int t;
int n, m, k;
ll a[maxn];
ll b[maxn];
ll bei[maxn];
ll x;
ll ans = 0;
int nex[maxn];
void build()
{
     
    nex[0] = 0;
    int pos = 0;
    for(int i= 2; i <= m; i ++)
    {
     
        while(pos && b[pos + 1] != b[i])
            pos = nex[pos];
        if(b[pos + 1] == b[i])
            pos ++;
        nex[i] = pos;
    }
}
void kmp()
{
     
    int pos = 0;
    for(int i = 1; i <= n; i ++)
    {
     
        while(pos && b[pos + 1] != a[i])
            pos = nex[pos];
        if(b[pos + 1] == a[i])
            pos ++;
        if(pos == m)
        {
     

            ans += bei[i - m + 1];
            pos = nex[pos];
            if(ans >= Mod)
                ans %= Mod;
        }

    }

}
int main()
{
     
    scanf("%d", &t);
    int cnt = 0;
    bei[0] = 0;
    bei[1] = 1;
    for(int i = 2; i < maxn; i ++)
    {
     
        bei[i] = bei[i - 1] * 2;
        if(bei[i] >= Mod)
            bei[i] %= Mod;
    }
    while(t --)
    {
     
        scanf("%d%d%d", &n, &m, &k);
        f.clear(k);
        ans = 0;
        for(int i = 1; i <= n; i ++)
        {
     
            scanf("%lld", &a[i]);
        }
        for(int i = 1; i <= m; i ++)
        {
     
            scanf("%lld", &b[i]);
        }
        for(int i = 1; i <= k; i ++)
        {
     
            scanf("%lld", &x);
            f.ins(x);
        }
        f.work();
        for(int i = 1; i <= n; i ++)
        {
     
           //cout<
            a[i] = f.get(a[i]);
            //cout<
        }
        //cout<
        for(int i = 1; i <= m; i ++)
        {
     
            b[i] = f.get(b[i]);
            //cout<
        }
        //cout<
        build();
        kmp();
        printf("%lld\n", ans);
    }

}


你可能感兴趣的:(随笔)