3439: Kpm的MC密码 trie+主席树
2016-02-27 13:48
579 查看
一开始写的fail树,然后沿着fail指针反向dfs。结果TLE啦。
看了一下题解,是把后缀相同转化为前缀相同,然后在trie树上有相同前缀的肯定在同一棵子树中,按dfs序建主席树就行啦。
其实在fail树上建主席树也是可以的。。一开始傻逼没有想到。。懒得改了。。
注意有相同的子串!
fail树暴力
看了一下题解,是把后缀相同转化为前缀相同,然后在trie树上有相同前缀的肯定在同一棵子树中,按dfs序建主席树就行啦。
其实在fail树上建主席树也是可以的。。一开始傻逼没有想到。。懒得改了。。
注意有相同的子串!
fail树暴力
#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<cstring> #define N 100005 using namespace std; int n,cnt,top; int a [26],p ,pos ,q ,stack ; bool flag ; char s ; vector<int> b ; vector<int> id ; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void insert(int x) { scanf("%s",s); int c,now=1,len=strlen(s); for (int i=0;i<len;i++) { c=s[i]-'a'; if (a[now][c]) now=a[now][c]; else now=a[now][c]=++cnt; } id[now].push_back(x); pos[x]=now; flag[now]=1; } inline void build_fail() { int t=0,w=1,now; q[1]=1; p[1]=0; while (t<w) { now=q[++t]; for (int i=0;i<26;i++) if (a[now][i]) { int k=p[now]; while (!a[k][i]) k=p[k]; p[a[now][i]]=a[k][i]; if (a[k][i]!=1) b[a[k][i]].push_back(a[now][i]); q[++w]=a[now][i]; } } } void dfs(int x) { if (flag[x]) for (int i=0;i<id[x].size();i++) stack[++top]=id[x][i]; for (int i=0;i<b[x].size();i++) dfs(b[x][i]); } int main() { // freopen("password.in","r",stdin); // freopen("password.out","w",stdout); n=read(); cnt=1; for (int i=0;i<26;i++) a[0][i]=1; for (int i=1;i<=n;i++) insert(i); build_fail(); for (int i=1;i<=n;i++) { top=0; dfs(pos[i]); sort(stack+1,stack+top+1); int k=read(); if (k>top) puts("-1"); else printf("%d\n",stack[k]); } return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<cstring> #define N 100005 using namespace std; int n,cnt,dfn,size; int a [26]; int in ,out ,root ,pos ,p ; char s ; int ls[5000005],rs[5000005],sum[5000005]; vector<int> id ; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void insert(int x) { scanf("%s",s); int c,now=1,len=strlen(s); for (int i=len-1;~i;i--) { c=s[i]-'a'; if (a[now][c]) now=a[now][c]; else now=a[now][c]=++cnt; } id[now].push_back(x); p[x]=now; } void dfs(int x) { in[x]=++dfn; pos[dfn]=x; for (int i=0;i<26;i++) if (a[x][i]) dfs(a[x][i]); out[x]=dfn; } void update(int l,int r,int x,int &y,int val) { y=++size; ls[y]=ls[x]; rs[y]=rs[x]; sum[y]=sum[x]+1; if (l==r) return; int mid=l+r>>1; if (val<=mid) update(l,mid,ls[x],ls[y],val); else update(mid+1,r,rs[x],rs[y],val); } int query(int x,int y,int k) { if (k>sum[y]-sum[x]) return -1; int l=1,r=n; while (l!=r) { int mid=l+r>>1; int tmp=sum[ls[y]]-sum[ls[x]]; if (tmp>=k) r=mid,x=ls[x],y=ls[y]; else l=mid+1,k-=tmp,x=rs[x],y=rs[y]; } return l; } int main() { // freopen("password.in","r",stdin); // freopen("password.out","w",stdout); n=read(); cnt=1; for (int i=0;i<26;i++) a[0][i]=1; for (int i=1;i<=n;i++) insert(i); dfs(1); for (int i=1;i<=cnt;i++) if (id[pos[i]].size()!=0) { update(1,n,root[i-1],root[i],id[pos[i]][0]); for (int j=1;j<id[pos[i]].size();j++) update(1,n,root[i],root[i],id[pos[i]][j]); } else root[i]=root[i-1]; for (int i=1;i<=n;i++) { int k=read(); printf("%d\n",query(root[in[p[i]]-1],root[out[p[i]]],k)); } return 0; }
相关文章推荐
- 产品经理成长之路
- 淘宝网提供的国内NPM镜像简介和使用方法
- ubuntu下安装rpm文件
- 一个在ActionBar上显示图标和菜单PopupMenu的小示例(19)
- 深圳运维、PM交流群 492384244
- 第51课:HadoopMapReduce多维排序解析与实战
- muShtaPmumixaMeerTyraniB.124
- 如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- Head First PMP – 7 – 成本管理(Cost Management)
- 产品经理面试常见问题
- 【Some】【搞逗】如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- 【Some】【搞逗】如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- 【Some】【搞逗】如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- 【Some】【搞逗】如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- 【Some】【搞逗】如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- 【Some】【搞逗】如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- 【Some】【搞逗】如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- 【Some】【搞逗】如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?
- 如何向外行解释产品经理频繁更改需求为何令程序员烦恼?
- npm 初识