Codeforces 1207 G. Indie Album

Codeforces 1207 G. Indie Album

解题思路

离线下来用SAM或者AC自动机就是一个单点加子树求和,套个树状数组就好了,因为这个题广义SAM不能存在 \(len[u] = len[fa]\) 的节点,需要特殊处理,所以写一个博客来贴板子,之前用Awd博客上的那个好像不太能处理干净。

code


/*program by mangoyang*/
#include <bits/stdc++.h>
#define inf ((ll) 1e18)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
	int ch = 0, f = 0; x = 0;
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
	for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
	if(f) x = -x;
}
 
const int N = 1600005;
 
vector<int> g[N], d[N], rt;
vector<pair<int, int> > q[N];
string str[N];
char strr[N];
int ans[N], n, m;
 
namespace Bit{
    int s[N];
    inline void modify(int x, int y){
        for(int i = x; i < N; i += i & -i) s[i] += y;
    }
    inline int query(int l, int r){
        int res = 0;
        for(int i = l - 1; i; i -= i & -i) res -= s[i];
        for(int i = r; i; i -= i & -i) res += s[i];
        return res;
    }
}
namespace SAM{
    vector<int> g[N];
    int ch[N][26], dfn[N], len[N], fa[N], sz[N], size = 1, tail = 1, cnt;
    inline int newnode(int x){ return len[++size] = x, size; }
    inline void ins(int c, int pos){
        int p = tail;
        if(ch[p][c]){
            if(ch[p][c] && len[ch[p][c]] == len[p] + 1){
                int np = ch[p][c];
                if(pos <= n) d[pos].push_back(np);
                return (void) (tail = np);
            }
            int np = newnode(len[p] + 1), q = ch[p][c];
            if(pos <= n) d[pos].push_back(np);
            fa[np] = fa[q], fa[q] = np;
            for(int i = 0; i < 26; i++) ch[np][i] = ch[q][i];
            for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = np;
            return (void) (tail = np);
        }
        int np = newnode(len[p] + 1);
        if(pos <= n) d[pos].push_back(np);
        for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
        if(!p) return (void) (fa[np] = 1, tail = np);
        int q = ch[p][c];
        if(len[q] == len[p] + 1) fa[np] = q;
        else{
            int nq = newnode(len[p] + 1);
            fa[nq] = fa[q], fa[q] = fa[np] = nq;
            for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
            for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
        } tail = np;
    }
    inline void addedge(){
        for(int i = 2; i <= size; i++) g[fa[i]].push_back(i);
    }
    inline void dfs(int u){
        dfn[u] = ++cnt, sz[u] = 1;
        for(int i = 0; i < (int) g[u].size(); i++)
            dfs(g[u][i]), sz[u] += sz[g[u][i]];
    }
}
inline void build(int u){
    int tmp = SAM::tail;
    for(int i = 0; i < (int) str[u].size(); i++)
        SAM::ins(str[u][i] - 'a', u);
    for(int i = 0; i < (int) g[u].size(); i++)
        build(g[u][i]);
    SAM::tail = tmp;
}
inline void solve(int u){
    for(int i = 0; i < (int) d[u].size(); i++)
        Bit::modify(SAM::dfn[d[u][i]], 1); 
    for(int i = 0; i < (int) q[u].size(); i++){
        int x = q[u][i].first, y = q[u][i].second;
        ans[x] = Bit::query(SAM::dfn[y], SAM::dfn[y] + SAM::sz[y] - 1);
    } 
    for(int i = 0; i < (int) g[u].size(); i++)        
        solve(g[u][i]);
    for(int i = 0; i < (int) d[u].size(); i++)
        Bit::modify(SAM::dfn[d[u][i]], -1);
}
int main(){
    read(n);
    for(int i = 1, x, y; i <= n; i++){
        read(x);
        if(x == 1) 
            cin >> str[i], rt.push_back(i);
        else 
            read(y), cin >> str[i], g[y].push_back(i);
    }
    for(int i = 0; i < (int) rt.size(); i++) 
        build(rt[i]);
    read(m);
    for(int i = 1, x; i <= m; i++){
        read(x), scanf("%s", strr); 
        int lenth = strlen(strr);
        for(int j = 0; j < lenth; j++)
            SAM::ins(strr[j] - 'a', n + 1);
        q[x].push_back(make_pair(i, SAM::tail));
        SAM::tail = 1;
    }
    SAM::addedge(), SAM::dfs(1);
    for(int i = 0; i < (int) rt.size(); i++)
        solve(rt[i]);
    for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
    return 0;
}

posted @ 2019-09-03 20:45  Joyemang33  阅读(333)  评论(0编辑  收藏  举报