[广义后缀自动机 SG值] 51Nod 1869 那些年,我们一起讲的故事
2017-06-13 21:58
387 查看
简直 在众人的帮助下理解了一个假题意 看完题解知道真题意
大概是每次加一个字符 这个串仍然要是Trie树的子串
直接建SAM 然后求SG值 不超过度数+1 也就是27
然后先手必胜 两边SG不同 那么按字典序数一数就好了
大概是每次加一个字符 这个串仍然要是Trie树的子串
直接建SAM 然后求SG值 不超过度数+1 也就是27
然后先手必胜 两边SG不同 那么按字典序数一数就好了
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cassert> #define cl(x) memset(x,0,sizeof(x)) using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void read(ll &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void read(char &x){ for (x=nc();!(x>='a' && x<='z');x=nc()); } const int N=400005; struct SAM{ struct state{ int link,len,next[26]; }st ; int last,ncnt; void Extend(int c){ if (st[last].next[c]){ int q=st[last].next[c]; if (st[q].len==st[last].len+1) last=q; else{ int nq=++ncnt; st[nq].link=st[q].link; st[q].link=nq; st[nq].len=st[last].len+1; for (int i=0;i<26;i++) st[nq].next[i]=st[q].next[i]; for (int p=last;p && st[p].next[c]==q;p=st[p].link) st[p].next[c]=nq; last=nq; } }else{ int cur=++ncnt,p; st[cur].len=st[last].len+1; for (p=last;p && !st[p].next[c];p=st[p].link) st[p].next[c]=cur; if (!p) st[cur].link=1; else{ int q=st[p].next[c]; if (st[q].len==st[p].len+1) st[cur].link=q; else{ int nq=++ncnt; st[nq].link=st[q].link; st[nq].len=st[p].len+1; for (int i=0;i<26;i++) st[nq].next[i]=st[q].next[i]; for (;p && st[p].next[c]==q;p=st[p].link) st[p].next[c]=nq; st[cur].link=nq; st[q].link=nq; } } last=cur; } } int tmp ,sum ,c ; inline void Sort(){ for (int i=1;i<=ncnt;i++) c[st[i].len]++; for (int i=1;i<=100000;i++) c[i]+=c[i-1]; for (int i=1;i<=ncnt;i++) tmp[c[st[i].len]--]=i; } ll cnt [27],tot ; int sg ; int clk,vst[27]; void Pre(){ for (int i=ncnt;i;i--){ int x=tmp[i]; ++clk; for (int j=0;j<26;j++){ if (!st[x].next[j]) continue; vst[sg[st[x].next[j]]]=clk; tot[x]+=tot[st[x].next[j]]; for (int k=0;k<=26;k++) cnt[x][k]+=cnt[st[x].next[j]][k]; } sg[x]=-1; for (int j=0;j<=26;j++) if (vst[j]!=clk) { sg[x]=j; break; } assert(sg[x]!=-1); cnt[x][sg[x]]++; tot[x]++; } } ll Tot(int x,int c){ return tot[x]-cnt[x][c]; } }A,B; char sa ,sb ; int na,nb; inline void solve(ll K,int c){ int x=1; while (1){ if (K==1 && B.sg[x]!=c) return; K-=B.sg[x]!=c; for (int j=0;j<26;j++){ if (!B.st[x].next[j]) continue; if (K<=B.Tot(B.st[x].next[j],c)){ x=B.st[x].next[j]; sb[++nb]='a'+j; break; }else{ K-=B.Tot(B.st[x].next[j],c); } } } } ll Sum ,Val ; inline void Solve(ll K){ for (int i=A.ncnt;i;i--){ int x=A.tmp[i]; Sum[x]=Val[x]=B.Tot(1,A.sg[x]); for (int j=0;j<26;j++){ if (!A.st[x].next[j]) continue; Sum[x]+=Sum[A.st[x].next[j]]; if (Sum[x]>1e18) Sum[x]=1e18; } } if (K>Sum[1]){ printf("K is too large!\n"); exit(0); } int x=1; while (1){ if (K<=Val[x]){ solve(K,A.sg[x]); return; }else{ K-=Val[x]; for (int j=0;j<26;j++){ if (!A.st[x].next[j]) continue; if (K<=Sum[A.st[x].next[j]]){ sa[++na]='a'+j; x=A.st[x].next[j]; break; }else{ K-=Sum[A.st[x].next[j]]; } } } } } struct edge{ int u,v,next; }G[N<<1]; int head ,inum; inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; } int val ; #define V G[p].v inline void dfs(int u,SAM &A){ int tmp=A.last; if (u) A.Extend(val[u]); for (int p=head[u];p;p=G[p].next) dfs(V,A); A.last=tmp; } int main(){ ll K; int n,p; char c; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(K); read(n); for (int i=1;i<=n;i++) read(p),read(c),add(p,i,++inum),val[i]=c-'a'; A.last=A.ncnt=1; dfs(0,A); A.Sort(); A.Pre(); cl(head); inum=0; read(n); for (int i=1;i<=n;i++) read(p),read(c),add(p,i,++inum),val[i]=c-'a'; B.last=B.ncnt=1; dfs(0,B); B.Sort(); B.Pre(); Solve(K); printf("%s\n%s\n",sa+1,sb+1); return 0; }
相关文章推荐
- 51nod 1647 小Z的trie 广义后缀自动机+倍增
- 那些码农的故事3---------那些年,我们一起迷茫过
- 51nod1869 那些年,我们一起讲的故事
- 【那些年,我们一起追的女孩】第十七章
- 那些年,我们一起泄露的内存
- 那些年,我们一起喜欢的诺基亚
- [BZOJ3277]串 广义后缀自动机
- BZOJ3926 [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机
- 那些年我们一起清除过的浮动
- 那些年,我们一起逆向的过程.
- bzoj 3926: 诸神眷顾的幻想乡 广义后缀自动机
- linux 下的编译器和调试器---那些年我们一起学习linux程序设计
- 【BZOJ 3277】串 广义后缀自动机
- BZOJ 3277 串 (广义后缀自动机)
- 那些年,我们一起参加过的高考
- 【那些年我们一起看过的论文】之《Fully Convolutional Networks for Semantic Segmentation》
- (转)那些年我们一起清除过的浮动
- 那些年,我们一起追过的女孩-会声会…
- 那些年,我们一起写的情诗
- 那些年,我们一起没学明白的傅里叶变换