bzoj 4477: [Jsoi2015]字符串树

原创 2016年06月01日 16:37:04

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4477

题意

在一棵树上的每条路都有一个字符串,有q个询问(u,v,S),u,v表示树上的两个节点,S表示一个字符串,求u到v路径上字符串中前缀是S的个数。

题解

将树路径上的字符串压缩到作为子节点的点中,之后用树链剖分维护一个可持久化trie树即可,时间复杂度为O(10qlogn)

code
#include <bits/stdc++.h>

#define N 100010

using namespace std;

char str[N][15];

int n, q, tot, QT;
int head[N];
int size[N], dfn[N], fa[N], top[N], son[N], w[N], ran[N];

struct ss
{
    int next, to;
    char ch[15];
};
ss Edge[N << 1];

void add(int x, int y, char *ch)
{
    Edge[++tot].next = head[x], Edge[tot].to = y;
    memcpy(Edge[tot].ch + 1, ch + 1, sizeof(char) * strlen(ch + 1));
    head[x] = tot;
}

namespace trie
{
    int cnt = 1;
    int sum[N * 10], son[N * 10][27], root[N];

    int Insert(int x, char *ch)
    {
        int tmp = ++cnt, y = cnt, len = strlen(ch + 1);
        for(int i = 1; i <= len; i++)
        {
            int p = ch[i] - 'a' + 1;
            for(int j = 0; j <= 26; j++)
                son[y][j] = son[x][j];
            sum[y] = sum[x] + 1, son[y][p] = ++cnt;
            x = son[x][p], y = son[y][p];
        }
        sum[y] = sum[x] + 1;
        return tmp;
    }

    int query(int l, int r, char *ch)
    {
        int x = root[l - 1], y = root[r], len = strlen(ch + 1);
        for(int i = 1; i <= len; i++)
        {
            int p = ch[i] - 'a' + 1;
            x = son[x][p], y = son[y][p];
        }
        return sum[y] - sum[x];
    }

    void build()
    {
        for(int i = 2; i <= n; i++)
            root[i] = Insert(root[i - 1], str[ran[i]]);
    }
}

void dfs(int u, int rt, int deep)
{
    size[u] = 1, fa[u] = rt, dfn[u] = deep;
    for(int i = head[u]; i; i = Edge[i].next)
    {
        int to = Edge[i].to;
        if(to == rt) continue;
        memcpy(str[to] + 1, Edge[i].ch + 1, sizeof(char) * strlen(Edge[i].ch + 1));
        dfs(to, u, deep + 1);
        size[u] += size[to];
        if(size[to] > size[son[u]]) son[u] = to;
    }
}

void dfs(int u, int tp)
{
    top[u] = tp, w[u] = ++QT, ran[QT] = u;
    if(!son[u]) return ;
    dfs(son[u], tp);
    for(int i = head[u]; i; i = Edge[i].next)
    {
        int to = Edge[i].to;
        if(to == fa[u] || to == son[u]) continue;
        dfs(to, to);
    }
}

int ask(int x, int y, char *ch)
{
    int ans = 0;
    while(top[x] != top[y])
    {
        if(dfn[top[x]] < dfn[top[y]]) swap(x, y);
        ans += trie::query(w[top[x]], w[x], ch);
        x = fa[top[x]];
    }
    if(dfn[x] > dfn[y]) swap(x, y);
    ans += trie::query(w[x] + 1, w[y], ch);
    return ans;
}

int main()
{
//  freopen("tt.in", "r", stdin);
    cin >> n;
    for(int x, y, i = 1; i < n; i++)
    {
        char ch[15];
        memset(ch, 0, sizeof(ch));
        scanf("%d%d%s", &x, &y, ch + 1);
        add(x, y, ch), add(y, x, ch);
    }
    dfs(1, 0, 1), dfs(1, 1);
    trie::build();
    cin >> q;
    for(int x, y, i = 1; i <= q; i++)
    {
        char ch[15];
        memset(ch, 0, sizeof(ch));
        scanf("%d%d%s", &x, &y, ch + 1);
        printf("%d\n", ask(x, y, ch));
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

[BZOJ]4477: [Jsoi2015]字符串树 可持久化trie

可持久化Trie
  • baidu_36797646
  • baidu_36797646
  • 2017年10月19日 15:02
  • 86

bzoj 4477: [Jsoi2015]字符串树 可持久化线段树

题意给出一棵树,每条边上都有一个长度不超过10的字符串。给出m个询问x y ch,求x到y的路径有多少个字符串的前缀是ch。 n,m...
  • qq_33229466
  • qq_33229466
  • 2017年03月09日 15:34
  • 300

【JSOI2015】字符串树 可持久Tire

题目描述 【故事背景】   萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树。字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子。 【问题描述】 ...
  • qq_25554407
  • qq_25554407
  • 2017年03月28日 14:32
  • 115

[JSOI2015][JZOJ4061]字符串树

题目大意一棵有nn个节点的树,每条边有一个长度ll不大于1010的字符串。有qq个询问,形如(x,y,s)(x,y,s)的询问,查询点xx到点yy的路径上,前缀为ss的边的数量。 1≤n,q≤100...
  • a_crazy_czy
  • a_crazy_czy
  • 2016年01月25日 20:50
  • 881

[BZOJ4487] [JSOI2015]染色问题

容斥原理
  • NiroBC
  • NiroBC
  • 2016年04月05日 14:58
  • 1260

bzoj 4475: [Jsoi2015]子集选取 数学

题意 1
  • qq_33229466
  • qq_33229466
  • 2017年04月18日 19:21
  • 368

bzoj 4481: [Jsoi2015]非诚勿扰 树状数组+数学期望

题意有n个女性和n个男性。每个女性的如意郎君列表都是所有男性的一个子集,并且可能为空。如果列表非空,她们会在其中选择一个男性作为自己最终接受的对象。将“如意郎君列表”中的男性按照编号从小到大的顺序呈现...
  • qq_33229466
  • qq_33229466
  • 2017年05月04日 14:44
  • 255

BZOJ 4475: [Jsoi2015]子集选取 快速幂

4475: [Jsoi2015]子集选取 Time Limit: 1 Sec  Memory Limit: 512 MB Submit: 217  Solved: 159 [Submit][St...
  • BlackJack_
  • BlackJack_
  • 2017年05月24日 15:02
  • 181

bzoj 4488: [Jsoi2015]最大公约数

Description 给定一个长度为 N 的正整数序列Ai对于其任意一个连续的子序列 {Al,Al+1...Ar},我们定义其权值W(L,R )为其长度与序列中所有元素的最大公约数的乘积,即W(L...
  • lqybzx
  • lqybzx
  • 2016年04月05日 20:27
  • 1327

【JZOJ4061】【JSOI2015】字符串树

DescriptionData ConstraintSolution这种题我们考虑什么用打棵字典树和lca来解决。我们对于一个点i,存储从i到根节点路径上的所有字符串,这可以用类似主席树的方法来解决。...
  • crybymyself
  • crybymyself
  • 2016年09月27日 17:10
  • 314
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bzoj 4477: [Jsoi2015]字符串树
举报原因:
原因补充:

(最多只允许输入30个字)