noip2019 training test events (xii) Problem C: substring (substring)

topic

Do you have a string.

You need to support both.

1: insert a character string at the end of c

2: querying the current string [l, r] the number of different sub-sub-string string

Forced Online

n,m<=50000

Thinking

violence:

SAM is the direct use of O (N . 3 ) of the

Correct answer:

Find that extend the operation of this problem is that the SAM 1.

After the setting operation once a string length len, the string will increase when the secondary extend to all sub-strings of bits len end.

These correspond to substrings of parents SAM is a tree leaf node to the root of the chain, and the leaf node indicates that your new child node S1 ⋯ len of the string.

So we consider the use of LCT dynamic maintenance of parents SAM tree.

(Disgusting ah, only the gods can make the scene come)

The last place with the same in a splay

We consider how to maintain an interval [l, r] the number of different sub-string.
This problem can be simplified to give you the number n, Always ask an interval [l, r] How many different numbers in there.
Thus, inclusion and exclusion! ! ! The number of the total number of non minus those last occurrence.

Consider pretreatment answer, from front to back in turn added to each number, add the i-th version of the i-th Chairman of the tree is about the i-bit plus 1. If the number present before, position is provided on one occurrence of LST, the j-th bit in the i-th version tree Chair minus 1.

So the interval the number of different sub-strings may be similarly resolved by the Chairman of the tree.

So, code code code! ! ! ! !

Long, 200 lines

Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+77;
int n,m,maxlen,rt[N][2];
struct SegmentTree
{
	int ls[N*100],rs[N*100],sz,siz[N*100];
	ll sumv[N*100];
	int cpyNode(int pre)
	{
		int x=++sz;
		ls[x]=ls[pre];
		rs[x]=rs[pre];
		sumv[x]=sumv[pre];
		siz[x]=siz[pre];
		return x;
	}
	void update(int & o,int pre,int l,int r,int ql,int qr,int v)
	{
		o=cpyNode(pre);
		if(ql==l && qr==r) { sumv[o]+=v,siz[o]++; return; }
		int mid=(l+r)>>1;
		if(qr<=mid)
			update(ls[o],ls[pre],l,mid,ql,qr,v);
		else if(ql>mid)
			update(rs[o],rs[pre],mid+1,r,ql,qr,v);
		else
			update(ls[o],ls[pre],l,mid,ql,mid,v),
			update(rs[o],rs[pre],mid+1,r,mid+1,qr,v);
	}
	int querySize(int o,int l,int r,int p)
	{
		if(l==r) return siz[o];
		int mid=(l+r)>>1;
		int Ans=siz[o];
		if(p<=mid) Ans+=querySize(ls[o],l,mid,p);
		else Ans+=querySize(rs[o],mid+1,r,p);
		return Ans;
	}
	ll querySum(int o,int l,int r,int p)
	{
		if(l==r) return sumv[o];
		int mid=(l+r)>>1;
		ll Ans=sumv[o];
		if(p<=mid) Ans+=querySum(ls[o],l,mid,p);
		else Ans+=querySum(rs[o],mid+1,r,p);
		return Ans;
	}
}rap;

namespace LCT
{
	static const int SIZE=2e5+77;
	int ch[SIZE][2],fa[SIZE];
	int pos[SIZE],len[SIZE];
	bool isrt(int x) { return !fa[x] || (ch[fa[x]][0] != x && ch[fa[x]][1] != x); }
	bool c(int x) { return ch[fa[x]][1]==x; }
	void rotate(int x)
	{
		int f=fa[x],p=fa[f],d=c(x);
		if(!isrt(f)) ch[p][c(f)]=x;
		fa[x]=p;
		ch[f][d]=ch[x][d^1]; fa[ch[f][d]]=f;
		ch[x][d^1]=f; fa[f]=x;
	}
	int findrt(int x) { return !isrt(x) ? findrt(fa[x]) : x; }
	void splay(int x)
	{
		swap(pos[findrt(x)],pos[x]);
		while(!isrt(x))
		{
			int f=fa[x];
			if(!isrt(f))
			{
				if(c(f)==c(x)) rotate(f);
				else rotate(x);
			}
			rotate(x);
		}
	}
	void access(int x,int i)
	{
		rt[i][0]=rt[i-1][0];
		rt[i][1]=rt[i-1][1];
		for(int v=0; x; v=x,x=fa[x])
		{
			splay(x);
			if(len[x] && pos[x])
			{
				int pl=pos[x]-len[x]+1,pr=pos[x]-len[fa[x]];
				if(pl>1) rap.update(rt[i][0],rt[i][0],1,maxlen,1,pl-1,pr-pl+1);
				rap.update(rt[i][1],rt[i][1],1,maxlen,pl,pr,pr);
			}
			if(ch[x][1]) pos[ch[x][1]]=pos[x];
			ch[x][1]=v;
			pos[v]=0;
			pos[x]=i;
		}
	}
	void cut(int x)
	{
		splay(x);
		pos[ch[x][0]]=pos[x];
		fa[ch[x][0]]=fa[x];
		ch[x][0]=0;
	}
	void link(int x,int y)
	{
		splay(x);
		fa[x]=y;
	}
}


struct SAM
{
	static const int SIZE=2e5+77;
	int nxt[SIZE][26],fa[SIZE],sz,pos[SIZE],len[SIZE],rt,last;
	SAM() { init(); }

	int newnode(int l,int id)
	{
		memset(nxt[sz],0,sizeof(nxt[sz]));
		pos[sz]=id;
		fa[sz]=0;
		len[sz]=l;
		return sz++;
	}

	void init()
	{
		sz=1;
		rt=newnode(0,0);
		last=rt;
	}

	void add(char x,int i)
	{
		int c=x-'a';
		int now=newnode(len[last]+1,i);
		LCT::len[now]=len[now];
		int p=last;
		while(p && !nxt[p][c])
		{
			nxt[p][c]=now;
			p=fa[p];
		}
		if(!p) LCT::link(now,fa[now]=rt);
		else
		{
			int q=nxt[p][c];
			if(len[p]+1==len[q])
				LCT::link(now,fa[now]=q);
			else
			{
				int u=newnode(len[p]+1,pos[q]);
				LCT::len[u]=len[u];
				for(int i=0; i<26; i++) nxt[u][i]=nxt[q][i];
				LCT::cut(q);
				LCT::pos[u]=LCT::pos[q];
				LCT::link(u,fa[u]=fa[q]);
				LCT::link(now,fa[now]=u);
				LCT::link(q,fa[q]=u);
				while(nxt[p][c]==q)
				{
					nxt[p][c]=u;
					p=fa[p];
				}
			}
		}
		LCT::access(now,i);
		
		last=now;
	}
}cxk;

char str[N];
int type;
int main()
{
	scanf("%d",&type);
	scanf("%s %d",str+1,&m);
	n=strlen(str+1);
	maxlen=n+m;
	for(int i=1; i<=n; i++)
		cxk.add(str[i],i);
	ll lastans=0;
	for(int i=1; i<=m; i++)
	{
		int opt;
		scanf("%d",&opt);
		if(opt==1)
		{
			char ch[5];
			scanf("%s",ch);
			str[++n]=(ch[0]-'a'+type*lastans)%26+'a';
			cxk.add(str[n],n);
		}
		else
		{
			int l,r;
			scanf("%d%d",&l,&r);
			l=(l-1+lastans*type)%n+1;
			r=(r-1+lastans*type)%n+1;
			ll val1=rap.querySum(rt[r][0],1,maxlen,l);
			ll val2=rap.querySum(rt[r][1],1,maxlen,l);
			ll val3=rap.querySize(rt[r][1],1,maxlen,l);
			lastans=1ll*(r-l+1)*(r-l+2)/2ll;
			lastans-=val1;
			lastans-=val2-1ll*(l-1)*val3;
			printf("%lld\n",lastans);
		}
	}
}
Published 703 original articles · won praise 392 · Views 140,000 +

Guess you like

Origin blog.csdn.net/Eric1561759334/article/details/100146248