bzoj 3879: SvT 접미사 로봇 + 접미사 트리 + 빈 트리
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
namespace IStream
{
char get_char()
{
static char *C,*mempool;
const int L=1<<20;
static char buffer[L];
if(C==mempool)
mempool=(C=buffer)+fread(buffer,1,L,stdin);
if(C==mempool) return EOF;
return *C++;
}
int get_int()
{
char c;
do c=get_char();while((c<'0' || c>'9') && c!='-');
int flag=1;
if(c=='-') flag=-1;
int re=0;
while(c>='0' && c<='9')
{
re=(re<<1)+(re<<3)+c-'0';
c=get_char();
}
return flag*re;
}
}
struct sam
{
int max_len,id;
sam *son[26],*parent;
sam(){}
}mempool[1000000],*root=&mempool[1],*last=root;
int now=1;
void Insert(int zm)
{
sam *p=last;
now++;
sam *np=&mempool[now];
mempool[now].id=now;
np->max_len=p->max_len+1;
while(p && !p->son[zm])
{
p->son[zm]=np;
p=p->parent;
}
if(!p) np->parent=root;
else
{
sam *q=p->son[zm];
if(q->max_len==p->max_len+1) np->parent=q;
else
{
now++;
sam *nq=&mempool[now];
mempool[now].id=now;
nq->max_len=p->max_len+1;
memcpy(nq->son,q->son,sizeof(nq->son));
nq->parent=q->parent;
q->parent=nq;
np->parent=nq;
while(p && p->son[zm]==q)
{
p->son[zm]=nq;
p=p->parent;
}
}
}
last=np;
}
char s[1000000];
int pos[1000000];
long long siz[1000000];
struct bian
{
int l,r;
}a[1000000];
int fir[1000000];
int timf[1000000];
int nex[1000000];
int pd[1000000];
int T;
int tot=1;
void add_edge(int l,int r)
{
a[++tot].l=l;
a[tot].r=r;
if(timf[l]!=T)
{
fir[l]=0;
timf[l]=T;
}
nex[tot]=fir[l];
fir[l]=tot;
}
int fa[1000000][21];
int id[1000000];
int deep[1000000];
int cnt=0;
void dfs(int u,int fro)
{
fa[u][0]=fro;
id[u]=++cnt;
deep[u]=deep[fro]+1;
for(int o=fir[u];o;o=nex[o])
{
if(a[o].r==fro) continue;
dfs(a[o].r,u);
}
}
void init()
{
for(int j=1;j<=19;j++)
for(int i=1;i<=now;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
long long ans=0;
void dp(int u,int fro)
{
siz[u]=(pd[u]==T?1:0);
long long v=(u==1?0:mempool[u].max_len-mempool[fro].max_len);
if(timf[u]!=T)
{
timf[u]=T;
fir[u]=0;
}
for(int o=fir[u];o;o=nex[o])
{
dp(a[o].r,u);
siz[u]+=siz[a[o].r];
}
ans+=v*siz[u]*(siz[u]-1)/2;
}
int get_lca(int x,int y)
{
if(deep[x]for(int i=19;i>=0;i--) if(deep[fa[x][i]]>=deep[y]) x=fa[x][i];
if(x==y) return x;
for(int i=19;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int aa[4000000];
bool cmp(int a,int b)
{
return id[a]int my_stack[4000000];
int main()
{
mempool[1].id=1;
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
using namespace IStream;
for(int i=n;i>=1;i--)
{
Insert(s[i]-'a');
pos[i]=last->id;
}
for(int i=2;i<=now;i++)
add_edge(mempool[i].parent->id,mempool[i].id);
dfs(1,0);
init();
for(int hh=1;hh<=m;hh++)
{
T++;
ans=0;
tot=1;
int nn;
nn=get_int();
for(int i=1;i<=nn;i++)
{
aa[i]=get_int();
aa[i]=pos[aa[i]];
pd[aa[i]]=T;
}
sort(aa+1,aa+1+nn,cmp);
int top=1;
my_stack[top]=1;
for(int i=1;i<=nn;i++)
{
if(aa[i]==aa[i-1]) continue;
int lca=get_lca(aa[i],my_stack[top]);
while(1)
{
if(top>1 && deep[lca]1]])
{
add_edge(my_stack[top-1],my_stack[top]);
top--;
}
else if(deep[lca]break;
}
else break;
}
if(my_stack[top]!=lca) my_stack[++top]=lca;
my_stack[++top]=aa[i];
}
while(top>1)
{
add_edge(my_stack[top-1],my_stack[top]);
top--;
}
dp(1,0);
printf("%lld
",ans);
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[CTSC2012] 익숙한 글제목의 뜻 여러 개의 주열이 있고, 매번 문의할 때마다 질문열을 여러 개의 연속 서브열로 나누며, 만약 한 서브열의 길이가 ≥L≥L이고 주열에 나타난 적이 있다면 합법적이다 만약 합법적인 하위 문자열의 총 길이가 ≥...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.