【洛谷】P5284 [十二省联考2019]字符串问题

我LOJ打不开了我会乱说?

当年愚蠢到用线段树建图的题……

我们首先需要一棵后缀树,根据“正串后缀自动机的fail树是反串的后缀树”,我们反着建一个后缀自动机,并构建正串后缀树

我们可以把要插入的A串或者B串插入到他们在后缀树对应的点,或者在一条边的中间

把A点拆成两个点,中间的边权是A串的长度

找到每个串对应的位置,同一条边上A按照长度顺序穿起来,然后B往自己下面的第一个A连边,这个树变成了一个根为起点的有向图

然后按照支配关系,A的出点往B连边

这个图如果不是DAG,那就是-1,是DAG可以通过dp求出来最长路的大小

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define MAXN 200005
#define fi first
#define se second
//#define ivorysi
#define enter putchar('
')
#define space putchar(' ')
typedef long long int64;
using namespace std;
template<class T>
void read(T &res) {
	res = 0;T f = 1;char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		res = res * 10 + c - '0';
		c = getchar();
	}
	res *= f;
}
template<class T>
void out(T x) {
	if(x < 0) {x = -x;putchar('-');}
	if(x >= 10) out(x / 10);
	putchar('0' + x % 10);
}
//-----定义区
char s[MAXN];
int n,na,nb;
struct node {
	int nxt,val,to;
}E[MAXN * 20];
int head[MAXN * 5],sumE,sumU;
int A[MAXN],B[MAXN],deg[MAXN * 5];
vector<pair<int,int> > v[MAXN * 2];
int64 dis[MAXN * 5];
queue<int> Q;
//-----

void add(int u,int v,int c) {
	E[++sumE].to = v;
	E[sumE].nxt = head[u];
	E[sumE].val = c;
	++deg[v];
	head[u] = sumE;
}
struct SAM {
	struct node {
		int len,par,nxt[26],cnt;
	}tr[MAXN * 2];
	int tail,last,root,left[MAXN];
	int fa[MAXN * 2][21];
	void Init() {
		tail = 0;
		root = last = ++tail;
		memset(tr[tail].nxt,0,sizeof(tr[tail].nxt));
		tr[tail].len =  tr[tail].par = 0;
	}
	void build(int c) {
		int nw = ++tail,p;
		memset(tr[nw].nxt,0,sizeof(tr[nw].nxt));
		tr[nw].len = tr[last].len + 1;tr[nw].cnt = 1;
		left[n - tr[nw].len + 1] = nw;
		for(p = last ; p && !tr[p].nxt[c] ; p = tr[p].par) {
			tr[p].nxt[c] = nw;
		}
		if(!p) tr[nw].par = root;
		else {
			int q = tr[p].nxt[c];
			if(tr[q].len == tr[p].len + 1) tr[nw].par = q;
			else {
				int cq = ++tail;
				tr[cq] = tr[q];tr[cq].cnt = 0;
				tr[cq].len = tr[p].len + 1;
				tr[q].par = tr[nw].par = cq;
				for(; p && tr[p].nxt[c] == q ; p = tr[p].par) {
					tr[p].nxt[c] = cq;
				}
			}
		}
		last = nw;
	}
	void build_tree() {
		for(int i = 1 ; i <= tail ; ++i) {
			v[i].clear();
			fa[i][0] = tr[i].par;
		}
		for(int j = 1 ; j <= 18 ; ++j) {
			for(int i = 1 ; i <= tail ; ++i) {
				fa[i][j] = fa[fa[i][j - 1]][j - 1];
			}
		}
	}
	void insert(int l,int r,int id) {
		int len = r - l + 1;
		int u = left[l];
		for(int j = 18 ; j >= 0 ; --j) {
			if(tr[fa[u][j]].len >= len) u = fa[u][j];
		}
		v[u].push_back(make_pair(len,id));
	}
}sam;
void build_graph() {
	for(int i = 1 ; i <= sam.tail ; ++i) {
		//out(i);space;out(sam.tr[i].par);space;out(sam.tr[i].len);enter;
		int t = v[i].size();
		sort(v[i].begin(),v[i].end());
		int p = sam.tr[i].par;
		for(int j = 0 ; j < t ; ++j) {
			if(v[i][j].se > 200000) {
				add(p,A[v[i][j].se - 200000],0);
				p = A[v[i][j].se - 200000];
			}
		}
		if(p) add(p,i,0);
		p = i;
		for(int j = t - 1 ; j >= 0 ; --j) {
			if(v[i][j].se <= nb) {
				add(B[v[i][j].se],p,0);
			}
			else p = A[v[i][j].se - 200000];
		}
	}
}
void Init() {
	scanf("%s",s + 1);
	n = strlen(s + 1);
	memset(dis,0,sizeof(dis));
	memset(deg,0,sizeof(deg));
	memset(head,0,sizeof(head));
	sam.Init();
	for(int i = n ; i >= 1 ; --i) {
		sam.build(s[i] - 'a');
	}
	sam.build_tree();
	sumE = 0;sumU = sam.tail + 1;
	read(na);
	for(int i = 1 ; i <= na ; ++i) {
		int l,r;
		read(l);read(r);
		A[i] = sumU;sumU += 2;
		add(A[i],A[i] + 1,r - l + 1);
		sam.insert(l,r,i + 200000);
	}
	read(nb);
	for(int i = 1 ; i <= nb ; ++i) {
		int l,r;read(l);read(r);
		B[i] = sumU;sumU++;
		sam.insert(l,r,i);
	}
	--sumU;
	int m;read(m);
	for(int i = 1 ; i <= m ; ++i) {
		int x,y;
		read(x);read(y);
		add(A[x] + 1,B[y],0);
	}
	build_graph();
}
void Solve() {
	for(int i = 1 ; i <= sumU ; ++i) {
		if(deg[i] == 0) {dis[i] = 0;Q.push(i);}
	}
	int64 ans = 0;
	while(!Q.empty()) {
		int u = Q.front();Q.pop();
		for(int i = head[u] ; i ; i = E[i].nxt) {
			int v = E[i].to;--deg[v];
			if(dis[v] < dis[u] + E[i].val) {
				dis[v] = dis[u] + E[i].val;
			}
			if(!deg[v]) Q.push(v);
		}
		ans = max(ans,dis[u]);
	}
	for(int i = 1 ; i <= sumU ; ++i) {
		if(deg[i]) {out(-1);enter;return;}
	}
	out(ans);enter;
}

int main() {
#ifdef ivorysi
	freopen("f1.in","r",stdin);
#endif
	int T;
	read(T);
	while(T--) {Init();Solve();}
}
原文地址:https://www.cnblogs.com/ivorysi/p/13292421.html