• 【洛谷】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();}
    }
    
  • 相关阅读:
    开发实例
    一张图解析FastAdmin中的表格列表的功能
    fastAdmin进阶
    detailFormatter bootstrapTable
    responseHandler
    自定义PDO封装类
    bootstrapTable
    Thread Safety
    FastAdmin 基本知识流程一栏
    thinkphp5 Request请求类
  • 原文地址:https://www.cnblogs.com/ivorysi/p/13292421.html
Copyright © 2020-2023  润新知