Submission #647417

#TimeUsernameProblemLanguageResultExecution timeMemory
647417ymmSelling RNA Strands (JOI16_selling_rna)C++17
100 / 100
277 ms47432 KiB
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,abm,bmi,bmi2")

#include <bits/stdc++.h>
#define Loop(x,l,r) for (ll x = (l); x < (ll)(r); ++x)
#define LoopR(x,l,r) for (ll x = (r)-1; x >= (ll)(l); --x)
typedef long long ll;
typedef std::pair<int, int> pii;
typedef std::pair<ll , ll > pll;
using namespace std;

const int N = 100'032;
const int S = 4096;

struct node
{
	bitset<S> *mask;
	int child[4];
} pool[50000000];

int rt_ltr, rt_rtl;

int new_node()
{
	static int nxt = 1;
	return nxt++;
}

int rna_to_int(char c)
{
	switch (c) {
	case 'A': return 0;
	case 'U': return 1;
	case 'C': return 2;
	case 'G': return 3;
	}
	return -1;
}

void trie_set(string s, int rt, int pos, int val)
{
	int t = rt;
	for (char c : s) {
		int x = rna_to_int(c);
		if (!pool[t].child[x])
			return;
		t = pool[t].child[x];
		if (pool[t].mask)
			(*pool[t].mask)[pos] = val;
	}
}

int trie_insert(string s, int rt)
{
	int t = rt;
	for (char c : s) {
		int x = rna_to_int(c);
		if (!pool[t].child[x])
			pool[t].child[x] = new_node();
		t = pool[t].child[x];
	}
	if (!pool[t].mask)
		pool[t].mask = new bitset<S>;
	return t;
}

string joi_rna[N], cus_pre[N], cus_suf[N];
int cus_pre_node[N], cus_suf_node[N];
int ans[N];
int n, m;

void set_joi_intrvl(int l, int r, int val)
{
	Loop (i,l,r) {
		trie_set(joi_rna[i], rt_ltr, i-l, val);
		reverse(joi_rna[i].begin(), joi_rna[i].end());
		trie_set(joi_rna[i], rt_rtl, i-l, val);
		reverse(joi_rna[i].begin(), joi_rna[i].end());
	}
}

int fast_bs_cnt(bitset<S> *a, bitset<S> *b)
{
	int *x = (int *)a;
	int *y = (int *)b;
	int ans = 0;
	Loop (i,0,S/8/sizeof(int))
		ans += __builtin_popcount(x[i] & y[i]);
	return ans;
}

int main()
{
	cin.tie(0) -> sync_with_stdio(false);
	cin >> n >> m;
	Loop (i,0,n) {
		cin >> joi_rna[i];
	}
	Loop (i,0,m) {
		cin >> cus_pre[i];
		cin >> cus_suf[i];
		reverse(cus_suf[i].begin(), cus_suf[i].end());
	}
	rt_ltr = new_node();
	rt_rtl = new_node();
	Loop (i,0,m) {
		cus_pre_node[i] = trie_insert(cus_pre[i], rt_ltr);
		cus_suf_node[i] = trie_insert(cus_suf[i], rt_rtl);
	}
	for (int l = 0; l < n; l += S) {
		int r = min(l+S, n);
		set_joi_intrvl(l, r, 1);
		Loop (cus,0,m) {
			auto m1 = pool[cus_pre_node[cus]].mask;
			auto m2 = pool[cus_suf_node[cus]].mask;
			ans[cus] += fast_bs_cnt(m1, m2);
			//ans[cus] += (*m1 & *m2).count();
		}
		set_joi_intrvl(l, r, 0);
	}
	Loop (i,0,m)
		cout << ans[i] << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...