模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合)

模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合)

Code:

#include <bits/stdc++.h>
using namespace std;
#define N 100010
map <int,int> son[N<<1]; char str[N]; int root[N<<1],pla[N],len;
int tot=1,last=1,pre[N<<1],dis[N<<1],in[N<<1];
namespace Sam
{
	void insert(int x,int id)
	{
		int p=last,np=last=++tot; dis[np]=dis[p]+1,pla[id]=np;
		while(p&&!son[p][x]) son[p][x]=np,p=pre[p];
		if(!p) {pre[np]=1;return;} int q=son[p][x];
		if(dis[q]==dis[p]+1) {pre[np]=q;return;} int nq=++tot;
		dis[nq]=dis[p]+1,son[nq]=son[q],pre[nq]=pre[q],pre[q]=pre[np]=nq;
		while(p&&son[p][x]==q) son[p][x]=nq,p=pre[p];;
	}
}
using namespace Sam;
struct Node {int son[2],size;}node[N<<7];
namespace Tree
{
	int cnt;
	void pushup(int p) {node[p].size=node[node[p].son[0]].size+node[node[p].son[1]].size;}
	void merge(int &x,int y)
	{
		if(!y) return; if(!x) {x=y;return;}
		node[++cnt]=node[x],x=cnt;
		merge(node[x].son[0],node[y].son[0]),merge(node[x].son[1],node[y].son[1]),pushup(x);
	}
	void change(int &p,int l,int r,int x)
	{
		if(!p) p=++cnt; if(l==r) {node[p].size++;return;}
		int mid=(l+r)>>1;
		if(x<=mid) change(node[p].son[0],l,mid,x);
		else change(node[p].son[1],mid+1,r,x); pushup(p);
	}
}
using namespace Tree;
int main()
{
	queue <int> q;
	scanf("%s",str+1),len=strlen(str+1);
	for(int i=1;i<=len;i++) insert(str[i]-'a',i);
	for(int i=1;i<=len;i++) change(root[pla[i]],1,len,i);
	for(int i=2;i<=tot;i++) in[pre[i]]++;
	for(int i=1;i<=tot;i++) if(!in[i]) q.push(i);
	while(!q.empty())
	{
		int p=q.front(); q.pop(),in[pre[p]]--;
		if(!in[pre[p]]) q.push(pre[p]);
		merge(root[pre[p]],root[p]);
	}
}

  

posted @ 2019-04-04 09:54  Yang1208  阅读(435)  评论(0编辑  收藏  举报