FJWC2020 Day3 题解

T1

Description

给你一棵 \(n\) 个点的树和 \(q\) 个询问。每次询问给出 \(a,d_a,b,d_b\),要你找到任意一个满足 \(dist(a,u)=d_a\)\(dist(b,u)=d_b\) 的点 \(u\)。找不到输出 \(-1\)

\(1\leq n,q\leq 10^6\)。时空限制 \(5s/512MB\)

Solution

要先实现一个函数 \(calc(x,y,d)\) 找到路径 \(x→y\) 上到 \(x\) 的距离为 \(d\) 的点。找不到返回 \(-1\)。令 \(z=lca(x,y)\),若 \(d\leq dist(x,z)\),则 \(ans=jump(x,d)\),否则 \(ans=jump(y,dist(x,y)-d)\)。其中 \(jump(x,d)\) 表示 \(x\)\(d\) 级祖先,可以用倍增实现。

接下来,设 \(c=lca(a,b)\),分 \(4\) 种情况讨论。

  1. \(u\)\(a\) 子树中。要满足 \(d_a+dist(a,b)=d_b\)。找到 \(u\) 子树中最深的节点 \(v\)\(ans=calc(u,v,d_a)\)
  2. \(u\)\(b\) 子树中,同理。
  3. \(u\) 在路径 \(a→b\) 上某个点 \(y\) 的子树里,\(y≠a,y≠b\)。此时要满足 \(d_a+d_b\geq dist(a,b)\),然后有: \(dist(a,y)+dist(b,y)=dist(a,b),d_a-d_b=dist(a,y)-dist(b,y)\)。可以解出 \(dist(a,y)\) 从而找到 \(y\),注意如果解出的 \(dist(a,y)\) 不是整数,无解。接下来,若 \(y≠c\),设 \(y\)\(a→b\) 路径上的子节点为 \(x\)。找到子树 \(y\) 中除了子树 \(x\) 以外的最深点 \(t\)\(ans=calc(y,t,d_a-dist(a,y))\)。若 \(y=c\)\(y\)\(a→b\) 路径上的子节点有两个,同样处理即可。记 \(Max(u)\)\(u\) 这个子树中最深的点的深度,那么需要预处理出每个点 \(Max\) 最大的 \(3\) 个子节点,以及每个点的子树中最深的点是哪个。
  4. \(u\) 在子树 \(c\) 外,需要满足 \(d_a-d_b=dist(a,c)-dist(b,c),d_a+d_b\geq dist(a,b)\)。设子树 \(c\) 外离 \(c\) 最远的点是 \(g_c\),那么 \(ans=calc(c,g_c,d_a-dist(a,c))\)\(g\) 用换根 \(\text{dp}\) 预处理即可。

时间复杂度 \(O(n\log n)\)

Code

#include <bits/stdc++.h>

using namespace std;

#define ll long long

template <class t>
inline void read(t & res)
{
    char ch;
    while (ch = getchar(), !isdigit(ch));
    res = ch ^ 48;
    while (ch = getchar(), isdigit(ch))
    res = res * 10 + (ch ^ 48);
}

template <class t>
inline void print(t x)
{
    if (x < 0)
    {
        putchar('-');
        x = ~x + 1;
    }
    if (x > 9) print(x / 10);
    putchar(x % 10 + 48);
}

const int e = 1e6 + 5, o = e << 1;

int a[e], b[e], dep[e], n, q, num, nxt[o], go[o], adj[e], c[e], d[e], pos[o], cnt, 
    logn[o], st[o][21], g[e];
int dfn[e], f[e][20], ans, s3[e], t3[e];

inline void add(int x, int y)
{
    nxt[++num] = adj[x]; adj[x] = num; go[num] = y;
    nxt[++num] = adj[y]; adj[y] = num; go[num] = x;
}

inline void dfs1(int u, int pa)
{
    dfn[u] = ++cnt;
    dep[u] = dep[pa] + 1;
    pos[cnt] = u; a[u] = b[u] = c[u] = d[u] = u;
    int i;
    for (i = 0; i < 19; i++) f[u][i + 1] = f[f[u][i]][i];
    for (i = adj[u]; i; i = nxt[i])
    {
        int v = go[i];
        if (v == pa) continue;
        f[v][0] = u;
        dfs1(v, u);
        pos[++cnt] = u;
        if (dep[c[v]] > dep[c[u]])
        {
            t3[u] = d[u];
            d[u] = c[u];
            c[u] = c[v];
            
            s3[u] = b[u];
            b[u] = a[u];
            a[u] = v;
        }
        else if (dep[c[v]] > dep[d[u]])
        {
            t3[u] = d[u];
            d[u] = c[v];
            
            s3[u] = b[u];
            b[u] = v;
        }
        else if (dep[c[v]] > dep[t3[u]])
        {
            t3[u] = c[v];
            s3[u] = v;
        }
    }
}

inline void init()
{
    int i, j;
    logn[0] = -1;
    for (i = 1; i <= cnt; i++)
    {
        logn[i] = logn[i >> 1] + 1;
        st[i][0] = pos[i];
    }
    for (j = 1; (1 << j) <= cnt; j++)
    for (i = 1; i + (1 << j) - 1 <= cnt; i++)
    {
        int u = st[i][j - 1], v = st[i + (1 << j - 1)][j - 1];
        if (dep[u] < dep[v]) st[i][j] = u;
        else st[i][j] = v;
    }
}

inline int lca(int l, int r)
{
    l = dfn[l]; r = dfn[r];
    if (l > r) swap(l, r);
    int k = logn[r - l + 1], u = st[l][k], v = st[r - (1 << k) + 1][k];
    return dep[u] < dep[v] ? u : v;
}

inline int dist(int x, int y)
{
    int z = lca(x, y);
    return dep[x] + dep[y] - (dep[z] << 1);
}

inline int jump(int x, int d)
{
    for (int i = 19; i >= 0; i--)
    if (d & (1 << i)) x = f[x][i];
    return x;
}

inline int calc(int x, int y, int d)
{
    int z = lca(x, y), dis = dep[x] + dep[y] - (dep[z] << 1);
    if (d <= dep[x] - dep[z]) return jump(x, d);
    else return jump(y, dis - d);
}

inline void dfs2(int u, int pa)
{
    int i;
    for (i = adj[u]; i; i = nxt[i])
    {
        int v = go[i];
        if (v == pa) continue;
        g[v] = g[u];
        if (a[u] == v)
        {
            if (dist(d[u], v) > dist(g[v], v)) g[v] = d[u];
        }
        else
        {
            if (dist(c[u], v) > dist(g[v], v)) g[v] = c[u];
        }
        dfs2(v, u);
    }
}

inline int solve12(int u, int v, int du, int dv, int z)
{
    int dis = dep[u] + dep[v] - (dep[z] << 1);
    if (dv == du + dis)
    {
        if (z == u)
        {
            int fv = calc(u, v, 1);
            if (fv != a[u])
            {
                if (dep[c[u]] - dep[u] >= du) return calc(u, c[u], du);
            }
            else if (dep[d[u]] - dep[u] >= du) return calc(u, d[u], du);
        }
        else if (dep[c[u]] - dep[u] >= du) return calc(u, c[u], du);
    }
    if (du == dv + dis)
    {
        if (z == v)
        {
            int fu = calc(v, u, 1);
            if (fu != a[v])
            {
                if (dep[c[v]] - dep[v] >= dv) return calc(v, c[v], dv);
            }
            else if (dep[d[v]] - dep[v] >= dv) return calc(v, d[v], dv);
        }
        else if (dep[c[v]] - dep[v] >= dv) return calc(v, c[v], dv);
    }
    return -1;
}

inline int solve3(int u, int v, int du, int dv, int z) 
{
    int dis = dep[u] + dep[v] - (dep[z] << 1);
    if (du + dv >= dis)
    {
        int del = du - dv;
        if ((dis + del) & 1) return -1;
        int a1 = dis + del >> 1, b1 = dis - a1, y = calc(u, v, a1), tot = du - a1;
        if (a1 < 0 || b1 < 0) return -1;
        if (y == u || y == v) return -1;
        if (y == z)
        {
            int fu = jump(u, dep[u] - dep[z] - 1), fv = jump(v, dep[v] - dep[z] - 1);
            if (a[z] != fu && a[z] != fv)
            {
                if (dep[c[z]] - dep[z] >= tot) return calc(z, c[z], tot);
            }
            else if (b[z] != fu && b[z] != fv)
            {
                if (dep[d[z]] - dep[z] >= tot) return calc(z, d[z], tot);
            }
            else
            {
                if (dep[t3[z]] - dep[z] >= tot) return calc(z, t3[z], tot);
            }
        }
        else if (a1 <= dep[u] - dep[z])
        {
            int ys = calc(u, v, a1 - 1);
            if (ys == a[y])
            {
                if (dep[d[y]] - dep[y] >= tot) return calc(y, d[y], tot);
            }
            else
            {
                if (dep[c[y]] - dep[y] >= tot) return calc(y, c[y], tot);
            }
        }
        else
        {
            int ys = calc(u, v, a1 + 1);
            if (ys == a[y])
            {
                if (dep[d[y]] - dep[y] >= tot) return calc(y, d[y], tot);
            }
            else
            {
                if (dep[c[y]] - dep[y] >= tot) return calc(y, c[y], tot);
            }
        }
    }
    return -1;
}

inline int solve4(int u, int v, int du, int dv, int z)
{
    int dis = dep[u] + dep[v] - (dep[z] << 1);
    if (du - dv == dep[u] - dep[v] && dep[u] - dep[z] <= du && dep[v] - dep[z] <= dv)
    {
        int dc = du - (dep[u] - dep[z]);
        if (dist(z, g[z]) >= dc) return calc(z, g[z], dc);
    }
    return -1;
}

int main()
{
    freopen("hunting.in", "r", stdin);
    freopen("hunting.out", "w", stdout);
    read(n); read(q);
    int u, v, i, du, dv;
    for (i = 1; i < n; i++) read(u), read(v), add(u, v);
    dfs1(1, 0);
    init();
    g[1] = 1;
    dfs2(1, 0);
    while (q--)
    {
        read(u); read(du); read(v); read(dv);
        if (u == v && du != dv)
        {
            puts("-1");
            continue;
        }
        ans = -1;
        if (u == v)
        {
            if (dist(u, g[u]) >= du) ans = calc(u, g[u], du);
            else if (dist(u, c[u]) >= du) ans = calc(u, c[u], du);
            print(ans); putchar('\n');
            continue;
        }
        int z = lca(u, v);
        ans = solve12(u, v, du, dv, z);
        if (ans == -1) ans = solve3(u, v, du, dv, z);
        if (ans == -1) ans = solve4(u, v, du, dv, z);
        print(ans); putchar('\n');
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T2

Description

给定一张 \(n\) 个点 \(m\) 条边的无向图,求有多少个非空点集的导出子图连通。

导出子图:仅保留这个点集中的点和端点都在这个点集中的边。

无向图的边 \((x,y)\) 都满足 \(|x-y|\leq 12\)

答案对 \(2\) 取模,\(1\leq n\leq 50\),时空限制 \(2s/512MB\)

Solution

导出子图连通也就是导出子图的连通块个数 \(=1\),否则连通块个数 \(>1\)

发现在 \(mod\ 4\) 意义下,\(2^1=2,2^k=0(k>1)\)

那么考虑求所有非空点集的导出子图的 \(2^{连通块个数}\) 之和。

这个问题相当于对每个导出子图的每个点黑白染色,要求连通的点必须同色的方案数之和。

那么记 \(f[i][s]\) 表示目前做到第 \(i\) 个点,\(s\) 是一个 \(12\) 位的 \(3\) 进制数,表示 \(i-11\sim i\)\(12\) 个点的状态(不在导出子图中,染成白色,染成黑色)。转移直接枚举 \(f[i-1][s]\)\(i\) 的状态即可。

最后答案如果是 \(2\), 输出 \(1\),否则输出 \(0\)

时间复杂度 \(O(3^{12}n)\)

有个神仙用连通性 \(\text{dp}\) + 神仙剪枝,过了。

Code

#include <bits/stdc++.h>

using namespace std;

template <class t>
inline void read(t & res)
{
    char ch;
    while (ch = getchar(), !isdigit(ch));
    res = ch ^ 48;
    while (ch = getchar(), isdigit(ch))
    res = res * 10 + (ch ^ 48);
}

const int o = 531446;

int p[55], f[55][o], n, m, ans;
bool bo[55][55];

inline void add(int &x, int y)
{
    x += y; x &= 3;
}

inline int calc(int x, int y)
{
    return x / p[y] % 3;
}

int main()
{
    freopen("graph.in", "r", stdin);
    freopen("graph.out", "w", stdout);
    read(n); read(m);
    int i, s, x, y, j;
    while (m--)
    {
        read(x); read(y);
        bo[x][y] = bo[y][x] = 1;
    }
    p[0] = 1;
    for (i = 1; i <= 12; i++) p[i] = p[i - 1] * 3;
    f[1][0] = f[1][p[11]] = f[1][2 * p[11]] = 1;
    for (i = 2; i <= n; i++)
    for (s = 0; s < p[12]; s++)
    if (f[i - 1][s])
    {
        int v = f[i - 1][s], t = s / 3;
        add(f[i][t], v);
        bool pd1 = 1, pd2 = 1;
        for (j = 0; j <= 11; j++)
        if (i - 12 + j >= 1 && bo[i][i - 12 + j])
        {
            int x = calc(s, j);
            if (x == 1) pd2 = 0;
            else if (x == 2) pd1 = 0;
        }
        if (pd1) add(f[i][t + p[11]], v);
        if (pd2) add(f[i][t + 2 * p[11]], v);
    }
    for (s = 0; s < p[12]; s++) add(ans, f[n][s]);
    (ans += 3) &= 3;
    if (ans == 2) ans = 1;
    cout << ans << endl;
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T3

Description

定义两个字符串是相似的,当且仅当至多存在一个 \(i\) ,使得这两个字符串中只有第 \(i\) 个字母不同。

你取出了这个字符串中所有长度为 \(m\) 的子串。你想知道,对于每个长度为 \(m\) 的子串,有多少个其它长度为 \(m\) 的子串与它相似。

\(n,m\leq 10^5\),时空限制 \(3s/512MB\)

Solution

记这个串为 \(S\)\(lcp(i,j)\) 表示 \(S[i\dots n]\)\(S[j\dots n]\) 的最长公共前缀长度,\(lcs(i,j)\) 表示 \(S[1\dots i]\)\(S[1\dots j]\) 的最长公共后缀长度。

问题转化为求有多少对 \(i,j\) 满足 \(lcp(i,j)+lcs(i+m-1,j+m-1)\geq m-1\)

先对 \(S\) 的正串和反串都建 \(SAM\) 以及 \(parent\) 树。记 \(p1[i]\) 为第一棵 \(parent\) 树上 \(S[1\dots i+m-1]\) 对应点的编号,\(p2[i]\) 为第二棵 \(parent\) 树上 \(S[i\dots n]\) 对应点的编号。式子转化为 \(dep1[lca1(p1[i],p1[j])]+dep2[lca2(p2[i],p2[j])]\geq m-1\)

接下来的这个实现方法可能过于麻烦,因为菜鸡看不懂标程只好自己瞎扯了。

考虑启发式合并,维护两棵树状数组 \(c,d\),下标是第二棵树的 \(dfs\) 序。

枚举 \(lca1(p1[i],p1[j])=x\),先考虑轻子树(包括点 \(x\))之间的贡献:我们先正序枚举轻儿子 \(v\)(包括点 \(x\)),然后把子树 \(v\) \(\text{dfs}\) 一遍。设 \(\text{dfs}\) 到节点 \(u\),如果 \(u\) 对应 \(S[1\dots i+m-1]\)。记 \(y\)\(p2[i]\) 到根的路径上,满足 \(dep2[y]>=m-1-dep1[x]\) 的最深节点(用倍增找)。然后在 \(c\) 上求出有多少个点在 \(y\) 子树中,就是对 \(ans[i]\) 的贡献。

然后再把 \(v\) 子树 \(\text{dfs}\) 一遍。在 \(c\) 上把 \(dfn2[u]\) 这个位置的值 \(+1\)

然后把轻子树都 \(\text{dfs}\) 一遍,清空 \(c\) 数组。然后倒序枚举轻儿子,再执行一遍上述过程,就把轻子树(包括点 \(x\))之间的贡献全部计算好了。

考虑重子树对轻子树的贡献,维护 \(d\) 数组,位置 \(i\) 表示重子树中有几个 \(dfn2=i\) 的点。把所有轻子树的点遍历一遍,在 \(d\) 数组上区间查,即可得到重子树对其贡献。

考虑轻子树对重子树的贡献。显然不可以把重子树 \(\text{dfs}\) 一遍。记 \(x\) 的重儿子为 \(son_x\)。枚举所有轻子树中的点 \(u\),显然会对满足 \(dfn1∈[dfn1[son_x],dfn1[son_x]+sze1[son_x]-1],dfn2∈[dfn2[y],dfn2[y]+sze2[y]-1]\) 的点产生 \(1\) 的贡献。这一部分的贡献相当于矩形加,单点查,离线 \(+\) 扫描线解决即可。

这到底要遍历多少次轻子树啊。

时间复杂度 \(O(n\log ^2n)\)。常数大的一批,但是 \(3s\) 还是稳的。

Code

#include <bits/stdc++.h>

using namespace std;

template <class t>
inline void print(t x)
{
    if (x > 9) print(x / 10);
    putchar(x % 10 + 48);
}

const int e = 2e5 + 15;

struct line
{
    int l, r, v;
    
    line(){}
    line(int _l, int _r, int _v) :
        l(_l), r(_r), v(_v) {} 
};
int c[e], d[e], son[e], n, m, ans[e], p1[e], p2[e], L, f[e][18], szeA[e], szeB[e], rt;
int lst_y[e], dfn_l, dfn_r, dfnA[e], dfnB[e], timA, timB, real_ans[e];
char s[e];
vector<line>g[e];
vector<int>h[e];

struct SAM
{
    struct point
    {
        int go[26];
    }t[e];
    int maxl[e], fa[e], tot = 1, lst = 1, id[e], anc[e][18], dep[e];
    vector<int>g[e];
    
    inline void insert(char s)
    {
        int c = s - 'a', i = lst;
        lst = ++tot;
        maxl[lst] = maxl[i] + 1;
        for (; i && !t[i].go[c]; i = fa[i]) t[i].go[c] = lst;
        if (!i) fa[lst] = 1;
        else
        {
            int j = t[i].go[c];
            if (maxl[j] == maxl[i] + 1) fa[lst] = j;
            else
            {
                int p;
                t[p = ++tot] = t[j];
                fa[p] = fa[j];
                fa[j] = fa[lst] = p;
                maxl[p] = maxl[i] + 1;
                for (; i && t[i].go[c] == j; i = fa[i]) t[i].go[c] = p;
            }
        } 
    }
    
    inline void build()
    {
        for (int i = 2; i <= tot; i++) g[fa[i]].push_back(i);
    }
}A, B;

inline void change(int *c, int x, int v)
{
    for (int i = x; i <= L; i += i & -i) c[i] += v;
}

inline int query(int *c, int x)
{
    int res = 0;
    for (int i = x; i; i -= i & -i) res += c[i];
    return res;
}

inline void dfsA(int u)
{
    dfnA[u] = ++timA;
    szeA[u] = 1;
    int len = A.g[u].size(), i;
    for (i = 0; i < len; i++)
    {
        int v = A.g[u][i];
        dfsA(v);
        szeA[u] += szeA[v];
        if (szeA[v] > szeA[son[u]]) son[u] = v;
    }
}

inline void dfsB(int u)
{
    dfnB[u] = ++timB;
    szeB[u] = 1;
    int len = B.g[u].size(), i;
    for (i = 0; i < 17; i++) f[u][i + 1] = f[f[u][i]][i];
    for (i = 0; i < len; i++)
    {
        int v = B.g[u][i];
        f[v][0] = u;
        dfsB(v);
        szeB[u] += szeB[v];
    }
}

inline int jumpB(int x, int d)
{
    for (int i = 17; i >= 0; i--)
    if (f[x][i] && B.maxl[f[x][i]] >= d) x = f[x][i];
    return x;
}

inline void add(int u)
{
    if (!A.id[u]) return;
    int pos = A.id[u], z = p2[pos];
    change(c, dfnB[z], 1);
}

inline void del(int u)
{
    if (!A.id[u]) return;
    int pos = A.id[u], z = p2[pos];
    change(c, dfnB[z], -1);
}

inline void ask(int u, int x)
{
    if (!A.id[u]) return;
    int pos = A.id[u], z = p2[pos], y = jumpB(z, m - 1 - A.maxl[x]);
    lst_y[u] = y;
    ans[pos] += query(c, dfnB[y] + szeB[y] - 1) - query(c, dfnB[y] - 1);
}

inline void calc_son(int u)
{
    if (!A.id[u]) return;
    int pos = A.id[u], z = p2[pos], y = lst_y[u];
    ans[pos] += query(d, dfnB[y] + szeB[y] - 1) - query(d, dfnB[y] - 1);
}

inline void ins(int u)
{
    if (!A.id[u]) return;
    int pos = A.id[u], z = p2[pos];
    change(d, dfnB[z], 1);
}

inline void clear(int u)
{
    if (!A.id[u]) return;
    int pos = A.id[u], z = p2[pos];
    change(d, dfnB[z], -1);
}

inline void join(int u)
{
    if (!A.id[u]) return;
    int y = lst_y[u];
    g[dfn_l].push_back(line(dfnB[y], dfnB[y] + szeB[y] - 1, 1));
    g[dfn_r + 1].push_back(line(dfnB[y], dfnB[y] + szeB[y] - 1, -1));
}

inline void dfs_add(int u)
{
    add(u);
    int len = A.g[u].size(), i;
    for (i = 0; i < len; i++) dfs_add(A.g[u][i]);
}

inline void dfs_del(int u)
{
    del(u);
    int len = A.g[u].size(), i;
    for (i = 0; i < len; i++) dfs_del(A.g[u][i]);
}

inline void dfs_ask(int u, int x)
{
    ask(u, x);
    int len = A.g[u].size(), i;
    for (i = 0; i < len; i++) dfs_ask(A.g[u][i], x); 
}

inline void dfs_cs(int u)
{
    calc_son(u);
    int len = A.g[u].size(), i;
    for (i = 0; i < len; i++) dfs_cs(A.g[u][i]); 
}

inline void dfs_ins(int u)
{
    ins(u);
    int len = A.g[u].size(), i;
    for (i = 0; i < len; i++) dfs_ins(A.g[u][i]);
}

inline void dfs_clear(int u)
{
    clear(u);
    int len = A.g[u].size(), i;
    for (i = 0; i < len; i++) dfs_clear(A.g[u][i]);
}

inline void dfs_join(int u)
{
    join(u);
    int len = A.g[u].size(), i;
    for (i = 0; i < len; i++) dfs_join(A.g[u][i]);
}

inline void dfsC(int u, bool op)
{
    int i, len = A.g[u].size();
    for (i = 0; i < len; i++)
    {
        int v = A.g[u][i];
        if (v != son[u]) dfsC(v, 0);
    }
    if (son[u]) dfsC(son[u], 1);
    
    ask(u, u); add(u);
    for (i = 0; i < len; i++)
    {
        int v = A.g[u][i];
        if (v != son[u])
        {
            dfs_ask(v, u);
            dfs_add(v);
        }
    }
    del(u);
    for (i = 0; i < len; i++)
    {
        int v = A.g[u][i];
        if (v != son[u]) dfs_del(v);
    }
    
    for (i = len - 1; i >= 0; i--)
    {
        int v = A.g[u][i];
        if (v != son[u])
        {
            dfs_ask(v, u);
            dfs_add(v);
        }
    }
    ask(u, u);
    for (i = 0; i < len; i++)
    {
        int v = A.g[u][i];
        if (v != son[u]) dfs_del(v);
    }
    
    calc_son(u);
    for (i = 0; i < len; i++)
    {
        int v = A.g[u][i];
        if (v != son[u]) dfs_cs(v);
    }
    
    if (op)
    {
        ins(u);
        for (i = 0; i < len; i++)
        {
            int v = A.g[u][i];
            if (v != son[u]) dfs_ins(v);
        }
    }
    else if (son[u]) dfs_clear(son[u]);
    
    if (son[u])
    {
        dfn_l = dfnA[son[u]]; 
        dfn_r = dfn_l + szeA[son[u]] - 1;
        join(u);
        for (i = 0; i < len; i++)
        {
            int v = A.g[u][i];
            if (v != son[u]) dfs_join(v);
        }
    }
}

int main()
{
    freopen("string.in", "r", stdin);
    freopen("string.out", "w", stdout);
    cin >> n >> m;
    int i, j;
    scanf("%s", s + 1);
    for (i = 1; i <= n; i++)
    {
        A.insert(s[i]);
        if (i >= m) A.id[A.lst] = i - m + 1, p1[i - m + 1] = A.lst;
    }
    for (i = n; i >= 1; i--)
    {
        B.insert(s[i]);
        if (i + m - 1 <= n) B.id[B.lst] = i, p2[i] = B.lst;
    }
    A.build(); B.build(); L = B.tot;
    dfsA(1); dfsB(1); dfsC(1, 0);
    memset(c, 0, sizeof(c));
    for (i = 1; i <= n - m + 1; i++) h[dfnA[p1[i]]].push_back(i);
    for (i = 1; i <= A.tot; i++)
    {
        int leng = g[i].size();
        for (j = 0; j < leng; j++)
        {
            line tmp = g[i][j];
            change(c, tmp.l, tmp.v);
            change(c, tmp.r + 1, -tmp.v);
        }
        int lenh = h[i].size();
        for (j = 0; j < lenh; j++)
        {
            int x = h[i][j];
            ans[x] += query(c, dfnB[p2[x]]);
        }
    }
    for (i = 1; i <= n - m + 1; i++)
    {
        print(ans[i]);
        if (i == n - m + 1) putchar('\n');
        else putchar(' ');
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/cyf32768/p/12233066.html
今日推荐