您的位置:首页 > 其它

【后缀自动机】Codeforces Round #305 (Div. 1) E. Mike and Friends

2015-05-29 13:44 295 查看
对所有的串加特殊字符隔开,单串建立后缀自动机。然后将每个的fa边反向建树,对树dfs得到dfs序,对dfs序建立线段树。询问离线,每个询问拆成1-(l-1)和1-r。。。按端点排序,然后每次加入线段树,查询k对应的节点的子树和。。。

#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 800005
#define maxm 1000005
#define eps 1e-12
#define mod 1000003
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
#pragma comment(linker, "/STACK:102400000,102400000")
#define pii pair<int, int>
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

const int alpha = 27;

struct node
{
int len, k;
node *next[alpha], *fa;
}*h[maxn], *tail, *last, *root, pool[maxm];

struct Edge
{
int v;
Edge *next;
}E[maxm], *H[maxn], *edges;

struct qu
{
int w, t, id, flag;
qu(int w = 0, int t = 0, int id = 0, int flag = 0) : w(w), t(t), id(id), flag(flag) {}
}q[maxm];

vector<int> vec[maxn];
int sum[maxn << 2];
int in[maxn];
int out[maxn];
int res[maxm];
string s[maxn];
int n, m, dfs_clock;

void addedges(int u, int v)
{
edges->v = v;
edges->next = H[u];
H[u] = edges++;
}

node* newnode(int len, int k)
{
tail->len = len;
tail->k = k;
tail->fa = 0;
memset(tail->next, 0, sizeof tail->next);
return tail++;
}

void add(int c, int k)
{
node *p = last, *np = newnode(p->len+1, k);
last = np;
for(; p && !p->next[c]; p = p->fa) p->next[c] = np;
if(!p) np->fa = root;
else {
node *q = p->next[c];
if(p->len + 1 == q->len) np->fa = q;
else {
node *nq = newnode(0, 0);
*nq = *q;
nq->len = p->len + 1;
q->fa = np->fa = nq;
for(; p && p->next[c] == q; p = p->fa) p->next[c] = nq;
}
}
}

void init()
{
dfs_clock = 0;
edges = E;
tail = pool;
last = root = newnode(0, 0);
memset(H, 0, sizeof H);
memset(res, 0, sizeof res);
}

int cmp(qu a, qu b)
{
return a.w < b.w;
}

void DFS(int u)
{
in[u] = ++dfs_clock;
for(Edge *e = H[u]; e; e = e->next) DFS(e->v);
out[u] = dfs_clock;
}

void pushup(int o)
{
sum[o] = sum[ls] + sum[rs];
}

void build(int o, int L, int R)
{
sum[o] = 0;
if(L == R) return;
int mid = (L + R) >> 1;
build(lson);
build(rson);
}

int query(int o, int L, int R, int ql, int qr)
{
if(ql <= L && qr >= R) return sum[o];
int mid = (L + R) >> 1, ans = 0;
if(ql <= mid) ans += query(lson, ql, qr);
if(qr > mid) ans += query(rson, ql, qr);
return ans;
}

void updata(int o, int L, int R, int v)
{
if(L == R) {
sum[o]++;
return;
}
int mid = (L + R) >> 1;
if(v <= mid) updata(lson, v);
else updata(rson, v);
pushup(o);
}

void work()
{
for(int i = 0; i <= n; i++) vec[i].clear();
for(int i = 1; i <= n; i++) {
cin >> s[i];
if(i != 1) add(26, 0);
for(int j = 0; s[i][j]; j++) {
add(s[i][j] - 'a', i);
vec[last->k].push_back(last - root);
}
}
for(int i = 1; i <= n; i++) {
h[i] = root;
for(int j = 0; s[i][j]; j++)
h[i] = h[i]->next[s[i][j] - 'a'];
}
for(node *p = pool + 1; p < tail; p++) addedges(p->fa - root, p - root);
DFS(0);
int tot = tail - pool;
int cnt = 0, l, r, kk;
for(int i = 1; i <= m; i++) {
scanf("%d%d%d", &l, &r, &kk);
q[cnt++] = qu(l-1, h[kk] - root, i, -1);
q[cnt++] = qu(r, h[kk] - root, i, 1);
}
sort(q, q+cnt, cmp);
build(1, 1, dfs_clock);
int j = 0;
while(q[j].w <= 0 && j < cnt) {
res[q[j].id] += query(1, 1, dfs_clock, in[q[j].t], out[q[j].t]) * q[j].flag;
j++;
}
for(int i = 1; i <= n; i++) {
for(int l = 0; l < vec[i].size(); l++) updata(1, 1, dfs_clock, in[vec[i][l]]);
while(q[j].w <= i && j < cnt) {
res[q[j].id] += query(1, 1, dfs_clock, in[q[j].t], out[q[j].t]) * q[j].flag;
j++;
}
}
for(int i = 1; i <= m; i++) printf("%d\n", res[i]);
}

int main()
{
while(scanf("%d%d", &n, &m)!=EOF) {
init();
work();
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: