• 题解「雅礼集训 2017 Day7」事情的相似度


    题目传送门

    Description

    给出一个长度为 (n)(01) 串为 (s),设 (t_i)(s_{1,2,..,i}),有 (m) 次查询,每次查询给出 (l,r),求 ([l,r]) 之间 (t_i) 的最长公共后缀长度的最大值。

    (n,mle 10^5)

    Solution

    本来不想写题解的,但想了想还是写一下吧。

    不难想到,假设 (f_i)(t_i) 在后缀自动机上对应的点,那么就相当于查询:

    [max{ ext{deep}( ext{lca}(f_i,f_j))},lle i,jle r ]

    考虑到在线不好搞,所以我们离线下来。然后你发现按左端点排序根本就不好做(不要问我怎么知道的),然后你发现按右端点排序之后就好做了。

    我们可以在加入一个点的时候把 ( ext{parent}) 树上都标记一下,那么如果过程中对于点 (u),如果已经标记过 (i) 了,那么说明对于当前右端点,左端点 (le i) 的区间 (u) 都可以产生贡献,就可以树状数组修改一下。由此我们也可以看出,我们需要保存的是最新标记的标记。

    复杂度显然是 (Theta(nlog^2n))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define MAXN 200005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    char s[MAXN];
    int n,m,ans[MAXN];
    
    struct Bit_Tree{
    	int maxn[MAXN];
    	int lowbit (int x){return x & (-x);}
    	void modify (int x,int v){x = n - x + 1;for (Int i = x;i <= n;i += lowbit (i)) maxn[i] = max (maxn[i],v);}
    	int query (int x){x = n - x + 1;int ans = 0;for (Int i = x;i;i -= lowbit (i)) ans = max (ans,maxn[i]);return ans;}
    }T1;
    
    struct node{
    	int ind,qL,qR;
    	bool operator < (const node &p)const{return qR < p.qR;}
    };
    vector <node> S[MAXN];
    
    int lst = 1,cnt = 1,ch[MAXN][2],len[MAXN],git[MAXN],fail[MAXN];
    
    void extend (int c){
    	int f = lst,q = ++ cnt;lst = q,len[q] = len[f] + 1;
    	while (f && !ch[f][c]) ch[f][c] = q,f = fail[f];
    	if (!f) fail[q] = 1;
    	else{
    		int x = ch[f][c];
    		if (len[x] == len[f] + 1) fail[q] = x;
    		else{
    			int p = ++ cnt;
    			fail[p] = fail[x],len[p] = len[f] + 1,memcpy (ch[p],ch[x],sizeof (ch[p]));
    			fail[x] = fail[q] = p;while (f && ch[f][c] == x) ch[f][c] = p,f = fail[f]; 
    		}
    	}
    }
    
    struct LCT{
    	int id[MAXN],fa[MAXN],son[MAXN][2];
    	bool rnk (int x){return son[fa[x]][1] == x;}
    	bool Isroot (int x){return son[fa[x]][rnk(x)] != x;}
    	void rotate (int x){
    		int y = fa[x],z = fa[y],k = rnk(x),w = son[x][!k];
    		if (!Isroot (y)) son[z][rnk(y)] = x;son[x][!k] = y,son[y][k] = w;
    		if (w) fa[w] = y;fa[x] = z,fa[y] = x;
    	}
    	void Pushdown (int x){
    		if (son[x][0]) id[son[x][0]] = id[x];
    		if (son[x][1]) id[son[x][1]] = id[x];
    	}
    	void Pushall (int x){
    		if (!Isroot (x)) Pushall (fa[x]);
    		Pushdown (x); 
    	}
    	void Splay (int x){
    		Pushall (x);
    		while (!Isroot (x)){
    			int y = fa[x];
    			if (!Isroot (y)) rotate (rnk(x) == rnk(y) ? y : x);
    			rotate (x); 
    		}
    	}
    	void Access (int x,int now){
    		for (Int y = 0;x;x = fa[y = x]){
    			Splay (x);
    			if (id[x]) T1.modify (id[x],len[x]);
    			son[x][1] = y,id[x] = now; 
    		}
    	}
    }T2;
    
    signed main(){
    	read (n,m),scanf ("%s",s + 1);
    	for (Int i = 1;i <= n;++ i) extend (s[i] - '0'),git[i] = lst;
    	for (Int i = 1,qL,qR;i <= m;++ i) read (qL,qR),S[qR].push_back (node{i,qL,qR});
    	for (Int i = 1;i <= cnt;++ i) T2.fa[i] = fail[i];
    	for (Int i = 1;i <= n;++ i){
    		T2.Access (git[i],i);
    		for (node g : S[i]) ans[g.ind] = T1.query (g.qL);  
    	} 
    	for (Int i = 1;i <= m;++ i) write (ans[i]),putchar ('
    ');
    	return 0;
    }
    
  • 相关阅读:
    排序-堆排序
    排序-计数排序
    Django之路——10 django的分页组件
    Django之路——9 Django的form组件的信息校验
    Django之路——8 cookie 和sessions
    Django之路——7 django与ajax
    Django之路——6 Django的模型层(二)
    Django之路——6 Django的模型层(一)
    Django之路——4 Django的视图层
    Django之路——5 Django的模板层
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/14567482.html
Copyright © 2020-2023  润新知