zoukankan      html  css  js  c++  java
  • 【字符串】区间本质不同子串个数_luoguP6292_调题笔记

    链接

    luogu P6292

    题解

    出题人的题解

    个人认为这个题解写得相当清晰,我就不写了。

    luogu上fuyuki的题解

    笔记

    • 这个程序要写三个数据结构。有点难处理。
    • 本质是要看清这三个数据结构分别要干什么事情。
      • 线段树:我没有维护区间等差数列,而是在每个位置记录了以该位置为左端点有多少应该被统计的字符串。因为LCT上每次修改的是把连续长度、统计位置的右端点连续的字符串右端点统一移到另一个地方,所以我们只需要支持区间加减1和区间求和就行了。
      • LCT:本质是要维护每个点代表的那一系列的字符串的最右出现位置并方便修改。所以LCT可以适当弱化一下功能————大可以把SAM或者后缀树建完之后再link出LCT。此时的link只用支持一个认父亲功能就行了;而cut则根本不需要。以及access每次找到当前这棵splay代表的长度的区间然后在线段树上区间加加减减就好了。
      • SAM:这就是个工具人,建出parenttree或者说反串后缀树之后就没有用了。他就是为LCT提供一个合理的树形结构。

    代码

    #include<bits/stdc++.h>
    #define LL long long
    #define MAXN 101000
    #define MAXM 201000
    using namespace std;
    template<typename T> void Read(T &cn)
    {
    	char c; int sig = 1;
    	while(!isdigit(c = getchar())) if(c == '-') sig = 0;
    	if(sig) {cn = c-48; while(isdigit(c = getchar())) cn = cn*10+c-48; }
    	else    {cn = 48-c; while(isdigit(c = getchar())) cn = cn*10+48-c; }
    }
    template<typename T> void Write(T cn)
    {
    	int wei = 0; T cm = 0; int cx = cn%10; cn/=10;
    	if(cn < 0 || cx < 0) {putchar('-'); cn = 0-cn; cx = 0-cx; }
    	while(cn)cm = cm*10+cn%10,cn/=10,wei++;
    	while(wei--)putchar(cm%10+48),cm/=10;
    	putchar(cx+48);
    }
    template<typename T> void WriteL(T cn) {Write(cn); puts(""); }
    template<typename T> void WriteS(T cn) {Write(cn); putchar(' '); }
    template<typename T> void Max(T &cn, T cm) {cn = cn < cm ? cm : cn; }
    template<typename T> void Min(T &cn, T cm) {cn = cn < cm ? cn : cm; }
    struct Seg{
    	struct node{
    		LL p, he;
    		int len;
    		void qing(int cn) {len = cn; p = he = 0; }
    		void zeng(int cn) {p = p+cn; he = he+len*cn; }
    	};
    	node t[MAXN*4+1];
    	int n;
    	void build(int cn, int l, int r)
    	{
    		t[cn].qing(r-l+1); if(l == r) return;
    		int zh = (l+r)>>1; build(cn<<1,l,zh); build((cn<<1)|1,zh+1,r);
    	}
    	void jia(int cn, int cl, int cr, int cm, int l, int r)
    	{
    		if(cl <= l && r <= cr) {t[cn].zeng(cm); return; }
    		tui(cn); int zh = (l+r)>>1;
    		if(cl <= zh) jia(cn<<1,cl,cr,cm,l,zh);
    		if(cr >  zh) jia((cn<<1)|1,cl,cr,cm,zh+1,r);
    		update(cn);
    	}
    	LL qiu(int cn, int cl, int cr, int l, int r)
    	{
    		if(cl <= l && r <= cr) return t[cn].he;
    		tui(cn); LL guo = 0; int zh = (l+r)>>1;
    		if(cl <= zh) guo = guo+qiu(cn<<1,cl,cr,l,zh);
    		if(cr > zh) guo = guo+qiu((cn<<1)|1,cl,cr,zh+1,r);
    		return guo;
    	}
    	void tui(int cn) {t[cn<<1].zeng(t[cn].p); t[(cn<<1)|1].zeng(t[cn].p); t[cn].p = 0; }
    	void update(int cn) {t[cn].he = t[cn<<1].he + t[(cn<<1)|1].he; }
    	void build(int cn) {n = cn; build(1,0,n); }
    	void jia(int cl, int cr, int cm) 
    	{
    //		printf("    in jia : (%d,%d) %d
    ",cl,cr,cm);
    		Max(cl,0); Max(cr,0); jia(1,cl,cr,cm,0,n); 
    	}
    	LL qiu(int cl, int cr) {return qiu(1,cl,cr,0,n); }
    }T;
    struct LCT{
    	struct node{
    		int fa, ch[2];
    		int endpos, da, len;
    		void qing(int cn = 0) {fa = ch[0] = ch[1] = 0; len = da = cn; endpos = 0; }
    		void bian(int cn) {endpos = cn; }
    	};
    	node t[MAXN*2+1];
    	int tlen;
    	int zhan[MAXN*2+1], zlen;
    	int isro(int cn) {return t[t[cn].fa].ch[0] != cn && t[t[cn].fa].ch[1] != cn; }
    	void pdown(int cn) {t[t[cn].ch[0]].bian(t[cn].endpos); t[t[cn].ch[1]].bian(t[cn].endpos); }
    	void update(int cn) {t[cn].da = max(max(t[t[cn].ch[0]].da, t[t[cn].ch[1]].da), t[cn].len); }
    	void rotate(int cn)
    	{
    		int fa = t[cn].fa, zu = t[fa].fa, ch1 = t[fa].ch[1] == cn, ch2 = t[zu].ch[1] == fa, hai = t[cn].ch[ch1^1];
    		if(!isro(fa)) t[zu].ch[ch2] = cn; t[cn].fa = zu;
    		t[cn].ch[ch1^1] = fa; t[fa].fa = cn;
    		t[fa].ch[ch1] = hai; t[hai].fa = fa;
    		update(fa); update(cn);
    	}
    	void splay(int cn)
    	{
    		if(!cn) return;
    		zlen = 0; int cm = cn;
    		while(!isro(cm)) cm = t[zhan[++zlen] = cm].fa; zhan[++zlen] = cm;
    		for(int i = zlen;i>=1;i--) pdown(zhan[i]);
    		while(!isro(cn)) {if(!isro(t[cn].fa)) rotate(t[cn].fa); rotate(cn); }
    	}
    	void access(int cn, int cm)
    	{
    //		printf("in access : cn = %d cm = %d
    ",cn,cm);
    		for(int i = 0;cn;cn = t[i = cn].fa)
    		{
    //			printf("  cn = %d i = %d
    ",cn,i);
    			splay(cn); splay(t[cn].fa);
    			int len1 = t[cn].len, len2 = t[t[cn].fa].len+1;
    //			printf("  len1 = %d len2 = %d
    ",len1,len2);
    			if(len2 <= len1) T.jia(t[cn].endpos-len1+1, t[cn].endpos-len2+1, -1);
    			pdown(cn); t[cn].endpos = cm;
    			if(len2 <= len1) T.jia(t[cn].endpos-len1+1, t[cn].endpos-len2+1, 1);
    			t[cn].ch[1] = i; update(cn);
    		}
    	}
    	void link_w(int cn, int fa, int clen) {t[cn].fa = fa; t[cn].len = t[cn].da = clen; }
    	void build(int cn) {tlen = cn; for(int i = 1;i<=cn;i++) t[i].qing(); }
    }LCT;
    struct SAM{
    	struct node{
    		int ch[26], link, len;
    		void qing() {memset(ch,0,sizeof(ch)); link = len = 0; }
    	};
    	node t[MAXN*2+1];
    	int tlen, last;
    	int pos[MAXN+1];
    	void build() {tlen = last = 1; t[1].qing(); }
    	void jia(int cn, int cm)
    	{
    		int cur = ++tlen; t[cur].qing(); pos[cm] = cur;
    		t[cur].len = t[last].len+1;
    		int p = last;
    		for(;p && !t[p].ch[cn];p = t[p].link) t[p].ch[cn] = cur;
    		if(!p) t[cur].link = 1;
    		else {
    			int q = t[p].ch[cn];
    			if(t[q].len == t[p].len+1) t[cur].link = q;
    			else {
    				int cln = ++tlen; t[cln] = t[q];
    				t[cln].len = t[p].len+1;
    				t[q].link = t[cur].link = cln;
    				for(;p && t[p].ch[cn] == q;p = t[p].link) t[p].ch[cn] = cln;
    			}
    		}
    		last = cur;
    	}
    	void outit()
    	{
    		for(int i = 1;i<=tlen;i++) 
    		{
    			printf("t[%d].link = %d .len = %d
    ",i,t[i].link,t[i].len);
    			for(int j = 0;j<=25;j++) if(t[i].ch[j]) printf("    .ch[%c] = %d
    ",j+'a',t[i].ch[j]);
    		}
    	}
    	void pre() {LCT.build(tlen); for(int i = 2;i<=tlen;i++) LCT.link_w(i, t[i].link, t[i].len); }
    	void gai(int cn) {LCT.access(pos[cn], cn); }
    }S;
    struct xunwen{
    	int l, r, pos;
    	void getit(int cn) {Read(l); Read(r); pos = cn; }
    	inline friend bool operator <(xunwen a, xunwen b) {return a.r == b.r ? a.l < b.l : a.r < b.r; }
    };
    int n,q;
    xunwen a[MAXM+1];
    char c[MAXN+1];
    LL ans[MAXM+1];
    void getit(char c[], int &clen)
    {
    	while(!isalpha(c[1] = getchar())); clen = 1;
    	while(isalpha(c[++clen] = getchar())); clen--;
    }
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	getit(c, n);
    	Read(q);
    	for(int i = 1;i<=q;i++) a[i].getit(i);
    	sort(a+1,a+q+1);
    	S.build();
    	for(int i = 1;i<=n;i++) S.jia(c[i]-'a',i);
    	S.pre(); T.build(n);
    	int xian = 0;
    	for(int i = 1;i<=n;i++)
    	{
    		S.gai(i);
    		while(xian < q && a[xian+1].r == i) xian++, ans[a[xian].pos] = T.qiu(a[xian].l,a[xian].r);
    	}
    	for(int i = 1;i<=q;i++) WriteL(ans[i]); 
    	return 0;
    }
    
  • 相关阅读:
    hdu 5115 区间dp ***
    CF 149D Coloring Brackets 区间dp ****
    区间dp总结
    hdu 5284 BestCoder Round #48 ($) 1001 水题 *
    vijos 1038 括号+路径 ***
    vijos 1037 ***
    vijos 1028 LIS *
    使用alpine 构建 golang 运行容器
    Go Http包解析:为什么需要response.Body.Close()
    如果open的file不close , 会有什么样的影响
  • 原文地址:https://www.cnblogs.com/czyarl/p/13947701.html
Copyright © 2011-2022 走看看