51nod1869 那些年,我们一起讲的故事
来源:互联网 发布:sql server 2008 视图 编辑:程序博客网 时间:2024/06/05 04:05
首先把trie的广义后缀自动机建出来,那么任选起点在trie上走就是在SAM 的起点开始走。在SAM上求出sg函数,先手必胜当且仅当两个自动机上的节点的sg函数值不同。对第一个SAM的每个节点求出它在第二个SAM上对应的合法的路径条数【注意是路径条数,不是节点个数】,然后按照求字典序k小的方法dfs就可以了。
注意几个细节:
1.后继状态总数会爆long long,但是显然总数只需要存到
2.一个点可能有好几条字母相同的出边,也就是其实给的不是trie。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define LL long longconst int maxn=500010;int trans[maxn][26],fail[maxn],val[maxn],sg[maxn],trie[maxn][26],rt[2],que[maxn],id[maxn],cnt[maxn],ord[2][maxn],vis[30],corr[maxn],n[2],t1[2],tot;LL size[maxn],sum[maxn],num[maxn][30],k;int add(int x,int u,int fl){ int nu,v,nv; val[nu=++tot]=val[u]+1; while (u&&!trans[u][x]) { trans[u][x]=nu; u=fail[u]; } if (!u) fail[nu]=rt[fl]; else { v=trans[u][x]; if (val[v]==val[u]+1) fail[nu]=v; else { val[nv=++tot]=val[u]+1; fail[nv]=fail[v]; fail[nu]=fail[v]=nv; for (int i=1;i<=26;i++) trans[nv][i]=trans[v][i]; while (u&&trans[u][x]==v) { trans[u][x]=nv; u=fail[u]; } } } return nu;}void build(int fl){ int x,hd,tl,u; char c[3]; scanf("%d",&n[fl]); for (int i=0;i<=n[fl];i++) for (int j=1;j<=26;j++) trie[i][j]=0; for (int i=1;i<=n[fl];i++) { scanf("%d%s",&x,c); if (!trie[corr[x]][c[0]-'a'+1]) trie[corr[x]][c[0]-'a'+1]=i; corr[i]=trie[corr[x]][c[0]-'a'+1]; } id[0]=rt[fl]=++tot; que[hd=tl=1]=0; while (hd<=tl) { u=que[hd++]; for (int i=1;i<=26;i++) if (trie[u][i]) { id[trie[u][i]]=add(i,id[u],fl); que[++tl]=trie[u][i]; } } for (int i=0;i<=n[fl];i++) cnt[i]=0; for (int i=rt[fl];i<=tot;i++) cnt[val[i]]++; for (int i=1;i<=n[fl];i++) cnt[i]+=cnt[i-1]; for (int i=rt[fl];i<=tot;i++) ord[fl][cnt[val[i]]--]=i; t1[fl]=tot-rt[fl]+1; for (int i=t1[fl];i>=1;i--) { u=ord[fl][i]; memset(vis,0,sizeof(vis)); for (int j=1;j<=26;j++) if (trans[ord[fl][i]][j]) vis[sg[trans[u][j]]]=1; for (int j=0;;j++) if (!vis[j]) { sg[u]=j; break; } }}void dfs(int fl,int u,LL k){ int x; if (size[u]>=k) { putchar('\n'); if (fl) return; for (int i=t1[1];i>=1;i--) { x=ord[1][i]; size[x]=sum[x]=(sg[x]!=sg[u]); for (int j=1;j<=26;j++) sum[x]+=sum[trans[x][j]]; } dfs(1,rt[1],k); return; } k-=size[u]; for (int j=1;j<=26;j++) if (sum[trans[u][j]]>=k) { putchar('a'+j-1); dfs(fl,trans[u][j],k); return; } else k-=sum[trans[u][j]];}int main(){ //freopen("c.in","r",stdin); //freopen("c.out","w",stdout); int u; scanf("%lld",&k); build(0); build(1); for (int i=t1[1];i>=1;i--) { u=ord[1][i]; num[u][sg[u]]=num[u][27]=1; for (int j=1;j<=26;j++) for (int k=0;k<=27;k++) num[u][k]+=num[trans[u][j]][k]; } for (int i=t1[0];i>=1;i--) { u=ord[0][i]; sum[u]=size[u]=num[rt[1]][27]-num[rt[1]][sg[u]]; for (int j=1;j<=26;j++) { sum[u]+=sum[trans[u][j]]; if (sum[u]>k+10) sum[u]=k+10; } } if (k>sum[1]) { printf("K is too large!\n"); return 0; } dfs(0,1,k);}
阅读全文
0 0
- 51nod1869 那些年,我们一起讲的故事
- [广义后缀自动机 SG值] 51Nod 1869 那些年,我们一起讲的故事
- 那些码农的故事3---------那些年,我们一起迷茫过
- 那些年,我们一起追的女孩
- 那些年 我们一起玩的ICQ
- 那些年我们一起的CSDN
- 那些年,我们一起学的C++
- 《那些年,我们一起追的女孩》
- 那些年我们一起追的风车...
- 那些年,我们一起追的HACK
- 那些年,我们一起喜欢的诺基亚
- 那些年,我们一起追的Android
- 那些年,我们一起写的情诗
- 那些年,我们一起学的嵌入式
- 那些年,我们一起走过的时光
- 那些年我们一起清除的浮动
- 那些年,我们一起逆向的过程.
- 那些年,我们一起看的毛片
- Mysql学习历程基本语法(3)--表操作
- 学习Linux-4.12内核网路协议栈(1.4)——协议栈的初始化(proto_init)
- 在HBase的shell命令行界面输入错误项按"退格键"删除,却怎么也删除不了
- TCP中的URG与PSH
- C++静态库
- 51nod1869 那些年,我们一起讲的故事
- 算法概论第八章练习题 8.14
- 仿自qsc的题解Markdown格式
- TCP四次挥手
- UVA
- Javascript
- hive------子查询
- 点云学习——孔洞修补
- 似然函数(likelihood function)