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

BZOJ3439 Kpm的MC密码

2014-12-01 16:42 232 查看
云神出的题= =,逼得蒟蒻要跳楼了

这道题的话。。。先把读入的字符串反转,然后建trie树

发现一个字符串的kpm串就是他的结尾字符的子树,于是对所有是字符串结尾的点按照dfs序展成一个序列。

问题转化为求区间第k大,用主席树什么的就好了。。。

/**************************************************************
Problem: 3439
User: rausen
Language: C++
Result: Accepted
Time:1500 ms
Memory:62744 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
typedef vector <int> Vec;
const int N = 100005;
const int Len = 300005;
const int M = 2000005;

struct trie_node {
int son[26], st, ed;
Vec tail;
} t[Len];

struct seg_node {
int lson, rson, num;
} tr[M];

int n, cnt_trie = 1, cnt_seq, cnt_seg;
int Tail
, root
;
char st[Len];
int len;
inline void read() {
char ch = getchar();
while (ch < 'a' || 'z' < ch) ch = getchar();
len = 0;
while ('a' <= ch && ch <= 'z')
st[++len] = ch, ch = getchar();
}

#define ch(j) (int) st[j] - 'a'
void build_trie() {
int i, j, now;
for (i = 1; i <= n; ++i) {
read();
reverse(st + 1, st + len + 1);
now = 1;
for (j = 1; j <= len; ++j) {
if (!t[now].son[ch(j)])
t[now].son[ch(j)] = ++cnt_trie;
now = t[now].son[ch(j)];
}
Tail[i] = now, t[now].tail.push_back(i);
}
}

#define mid (l + r >> 1)
void insert(int &p, int l, int r, int pos) {
tr[++cnt_seg] = tr[p], p = cnt_seg, ++tr[p].num;
if (l == r) return;
if (pos <= mid) insert(tr[p].lson, l, mid, pos);
else insert(tr[p].rson, mid + 1, r, pos);
}

int query(int i, int j, int rank) {
i = root[i - 1], j = root[j];
if (tr[j].num - tr[i].num < rank) return -1;
int l = 1, r = n;
while (l != r) {
if (tr[tr[j].lson].num - tr[tr[i].lson].num >= rank)
r = mid, i = tr[i].lson, j = tr[j].lson;
else {
rank -= tr[tr[j].lson].num - tr[tr[i].lson].num;
l = mid + 1, i = tr[i].rson, j = tr[j].rson;
}
}
return l;
}

void dfs(int p) {
int i, sz = t[p].tail.size();
if (sz) {
t[p].st = ++cnt_seq, root[cnt_seq] = root[cnt_seq - 1];
for (i = 0; i < sz; ++i)
insert(root[cnt_seq], 1, n, t[p].tail[i]);
}
for (i = 0; i < 26; ++i)
if (t[p].son[i])
dfs(t[p].son[i]);
if (sz)
t[p].ed = cnt_seq;
}

int main() {
int i, x;
scanf("%d\n", &n);
build_trie();
dfs(1);
for (i = 1; i <= n; ++i) {
scanf("%d", &x);
printf("%d\n", query(t[Tail[i]].st, t[Tail[i]].ed, x));
}
}


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