模板题求助
查看原帖
模板题求助
224229
Caicz楼主2020/10/9 20:43

rt,标题吸引大佬回答
具体思路:广义SAM,然后动态开点线段树处理每个SAM上的结点,线段树范围为 1-m ,然后在parent树上进行线段树合并。对于每个询问倍增在parent树上找到从 1 开始的等效区间,线段树查询

调了一下午+一晚上,没找出问题,cf第二个点 某个询问应该输出 4 1 ,程序输出了 3 1,数据点太大,弄不下来

求 hack 数据,或指出具体错误

谢绝无意义评论

代码

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=500005;
const int maxm=50005;
int q,m,rt[maxn<<1];
char s[maxn],temp[maxm];

inline int read(void)
{
	int num,sign=1;char c;
	while(!isdigit(c=getchar()))if(c=='-')sign=0;num=c-'0';
	while(isdigit(c=getchar()))num=(num<<1)+(num<<3)+c-'0';
	return sign?num:-num;
}
struct nodeans
{
	int ans,id;
	friend bool operator>(nodeans x,nodeans y){return x.ans==y.ans?x.id<y.id:x.ans>y.ans;}
};
inline nodeans max(nodeans x,nodeans y){return x>y?x:y;}

struct segment_tree
{
	int tot;
	struct node
	{
		int ls,rs;
		nodeans si;
	}tr[(maxn+maxm)*26];
	void modify(int &u,int l,int r,int pos)
	{
		if(!u)u=++tot;
		if(l==r){++tr[u].si.ans,tr[u].si.id=l;return;}
		int mid=(l+r)>>1;
		if(mid>=pos)modify(tr[u].ls,l,mid,pos);
		else modify(tr[u].rs,mid+1,r,pos);
		tr[u].si=max(tr[tr[u].ls].si,tr[tr[u].rs].si);
	}
	void merge(int &x,int y,int l,int r)
	{
		if(!x||!y)return x=x|y,void();
		if(l==r){tr[x].si.ans+=tr[y].si.ans;return;}
		int mid=(l+r)>>1;
		merge(tr[x].ls,tr[y].ls,l,mid);
		merge(tr[x].rs,tr[y].rs,mid+1,r);
		tr[x].si=max(tr[tr[x].ls].si,tr[tr[x].rs].si);
	}
	nodeans query(int u,int l,int r,int x,int y)
	{
		if(l>=x&&r<=y)return tr[u].si;
		int mid=(l+r)>>1;
		if(mid>=y)return query(tr[u].ls,l,mid,x,y);
		else if(mid<x)return query(tr[u].rs,mid+1,r,x,y);
		return max(query(tr[u].ls,l,mid,x,y),query(tr[u].rs,mid+1,r,x,y));
	}
}supccz;

struct suffix_automaton
{
	int la=1,tot=1,ins[(maxn+maxm)<<1],cnt;
	int head[(maxn+maxm)<<1],cnt_edge,pos[maxn];
	int st[22][(maxn+maxm)<<1];
	struct node
	{
		int fa,len,ch[26];
	}tr[(maxn+maxm)<<1];
	struct edge
	{
		int v,last;
	}e[(maxn+maxm)<<1];
	inline void addedge(int u,int v){e[++cnt_edge].last=head[u],e[cnt_edge].v=v,head[u]=cnt_edge;}
	inline void insert(int x,int id)
	{
		if(tr[la].ch[x])
		{
			int p=la,u=tr[la].ch[x];
			if(tr[p].len+1==tr[u].len)
			{
				la=u;
				if(id)supccz.modify(rt[u],1,m,id);
				else pos[++cnt]=la;
				return;
			}
			int nu=++tot;
			tr[nu]=tr[u],tr[nu].len=tr[p].len+1;
			while(p&&tr[p].ch[x]==u)tr[p].ch[x]=nu,p=tr[p].fa;
			tr[u].fa=nu,la=nu;
			if(id)supccz.modify(rt[nu],1,m,id);
			else pos[++cnt]=la;
			return;
		}
		int p=la,u=++tot;
		tr[u].len=tr[p].len+1;
		while(p&&!tr[p].ch[x])tr[p].ch[x]=u,p=tr[p].fa;
		if(!p)tr[u].fa=p+1;
		else
		{
			int q=tr[p].ch[x];
			if(tr[q].len==tr[p].len+1)tr[u].fa=q;
			else
			{
				int nu=++tot;
				tr[nu]=tr[q],tr[nu].len=tr[p].len+1;
				while(p&&tr[p].ch[x]==q)tr[p].ch[x]=nu,p=tr[p].fa;
				tr[q].fa=tr[u].fa=nu;
			}
		}
		la=u;
		if(id)supccz.modify(rt[u],1,m,id);
		else pos[++cnt]=la;
	}
	void dfs(int u)
	{
		for(register int i=head[u];i;i=e[i].last)
		{
			int v=e[i].v;st[0][v]=u;
			dfs(v);
			supccz.merge(rt[u],rt[v],1,m);
		}
	}
	inline void linktree(void)
	{
		for(register int i=2;i<=tot;++i)addedge(tr[i].fa,i);dfs(1);
		for(register int j=1;j<=21;++j)
			for(register int i=1;i<=tot;++i)st[j][i]=st[j-1][st[j-1][i]];
	}
	inline int getsq(int x,int len)
	{
		x=pos[x];
		for(register int i=21;~i;--i)if(st[i][x]&&tr[st[i][x]].len>=len)x=st[i][x];
		return x;
	}
	inline void solve(int l,int r,int x,int y)
	{
		nodeans ans=supccz.query(rt[getsq(y,y-x+1)],1,m,l,r);
		if(!ans.ans)ans.id=l;
		printf("%d %d\n",ans.id,ans.ans);
	}
}ccz;

signed main(void)
{
	scanf("%s",s);
	m=read();
	for(register int i=1;i<=m;++i)
	{
		ccz.la=1;
		scanf("%s",temp);
		int len=strlen(temp);
		for(register int j=0;j<len;++j)ccz.insert(temp[j]-'a',i);
	}	
	ccz.la=1;
	int len=strlen(s);
	for(register int i=0;i<len;++i)ccz.insert(s[i]-'a',0);
	ccz.linktree();
	q=read();
	for(register int l,r,ql,qr,i=1;i<=q;++i)
	{
		l=read(),r=read(),ql=read(),qr=read();
		ccz.solve(l,r,ql,qr);
	}
	return 0;
}

2020/10/9 20:43
加载中...