您的位置:首页 > 产品设计 > 产品经理

3439: Kpm的MC密码 trie+主席树

2016-02-27 13:48 579 查看
一开始写的fail树,然后沿着fail指针反向dfs。结果TLE啦。

看了一下题解,是把后缀相同转化为前缀相同,然后在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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: