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

BZOJ3439 Kpm的MC密码(可持久化trie)

2018-09-20 19:56 555 查看

  将串反过来就变成查询前缀了。考虑建一棵可持久化trie,查询时二分答案,均摊一下复杂度即为O(mlogn)。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
#define N 100010
#define M 300010
int n,cnt=0,root
,size
;
vector<int> a
;
struct data{int ch[26],x;
}tree[M<<1];
void ins(int &k,int x,int p)
{
tree[++cnt]=tree[k],k=cnt;tree[k].x++;
if (p==size[x]) return;
ins(tree[k].ch[a[x]

],x,p+1); } int query(int k,int x,int p) { if (!k) return 0; if (p==size[x]) return tree[k].x; return query(tree[k].ch[a[x][p]],x,p+1); } int main() { #ifndef ONLINE_JUDGE freopen("bzoj3439.in","r",stdin); freopen("bzoj3439.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<=n;i++) { char c=getchar(); while (c<'a'||c>'z') c=getchar(); while (c>='a'&&c<='z') a[i].push_back(c-'a'),c=getchar(); root[i]=root[i-1];size[i]=a[i].size(); reverse(a[i].begin(),a[i].end()); ins(root[i],i,0); } for (int i=1;i<=n;i++) { int x=read(); int l=1,r=n,ans=-1; while (l<=r) { int mid=l+r>>1; if (query(root[mid],i,0)>=x) ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); } return 0; }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: