当前位置: 移动技术网 > IT编程>开发语言>C/C++ > BZOJ4598: [Sdoi2016]模式字符串(点分治 hash)

BZOJ4598: [Sdoi2016]模式字符串(点分治 hash)

2018年12月06日  | 移动技术网IT编程  | 我要评论

昆山二手房信息,张育汉,苏泊尔电饭煲维修

题意

题目链接

sol

直接考虑点分治+hash匹配

\(up[i]\)表示\(dep \% m = i\)的从下往上恰好与前\(i\)位匹配的个数

\(down\)表示\(dep \% m = i\)的从上往下恰好与后\(i\)位匹配的个数

暴力转移即可

复杂度:\(o(nlog^2n)??\)

代码写起来有一车边界

#include<bits/stdc++.h>
#define ull unsigned long long 
#define ll long long 
#define int long long 
#define siz(v) ((int)v.size())
using namespace std;
const int maxn = 1e6 + 10, inf = 1e10 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int n, m, root, siz[maxn], mx[maxn], siz, dep[maxn], up[maxn], down[maxn], su[maxn], sd[maxn];
ll ans;
bool det[maxn];
char a[maxn], b[maxn];
vector<int> v[maxn];
ull hs[maxn], hp[maxn], po[maxn], base = 1331;
map<ull, bool> mp;
void findroot(int x, int fa) {
    siz[x] = 1; mx[x] = 0;
    for(int i = 0; i < siz(v[x]); i++) {
        int to = v[x][i];
        if(to == fa || det[to]) continue;
        findroot(to, x);
        siz[x] += siz[to]; mx[x] = max(mx[x], siz[to]);
    }
    mx[x] = max(mx[x], siz - siz[x]);
    if(mx[x] < mx[root]) root = x;
}
int dfs(int x, int fa, ull now) {
    siz[x] = 1;
    dep[x] = dep[fa] + 1;
    now = now * base + a[x];
    if(hp[dep[x]] == now) up[(dep[x] - 1) % m + 1]++, ans += sd[m - (dep[x] - 1) % m];
    if(hs[dep[x]] == now) down[(dep[x] - 1) % m + 1]++, ans += su[m - (dep[x] - 1) % m];
   // printf("%d %d\n", x, ans);
    int td =1;
    for(int i = 0; i < siz(v[x]); i++) {
        int to = v[x][i];
        if(to == fa || det[to]) continue;
        td = max(td, dfs(to, x, now) + 1); 
        siz[x] += siz[to];
    }
    return td;
}
void work(int x) {
    int tk = 0, tmp = 0;
    det[x] = 1; dep[x] = 1; su[1] = sd[1] = 1;//tag;
    for(int i = 0; i < siz(v[x]); i++) {   
        int to = v[x][i];   
        if(det[to]) continue;
        tk = min(m, dfs(to, x, a[x]) + 1), tmp = max(tmp, tk);
        for(int j = 1; j <= tk; j++) su[j] += up[j], sd[j] += down[j], up[j] = down[j] = 0;
    }
    for(int i = 1; i <= tmp; i++) su[i] = sd[i] = 0;
    for(int i = 0; i < siz(v[x]); i++) {
        int to = v[x][i];
        if(to == x || det[to]) continue;
        siz = siz[to]; root = 0; findroot(to, x); 
        work(root);
    }
}
void init() {
    for(int i = 1; i <= n; i++) v[i].clear();
    memset(det, 0, sizeof(det));
    memset(siz, 0, sizeof(siz));
    memset(mx, 0, sizeof(mx));
    ans = 0;    
}
void solve() {

    n = read(); m = read();
    init();
    scanf("%s", a + 1);
    for(int i = 1; i <= n - 1; i++) {
        int x = read(), y = read();
        v[x].push_back(y); v[y].push_back(x);
    }
    for(int i = 1; i <= n; i++) reverse(v[i].begin(), v[i].end());
    scanf("%s", b + 1); po[0] = 1;
    for(int i = 1; i <= n; i++) {
        hp[i] = hp[i - 1] + b[(i - 1) % m + 1] * po[i - 1];
        hs[i] = hs[i - 1] + b[m - (i - 1) % m] * po[i - 1];
        po[i] = base * po[i - 1];
    }
    siz = n; mx[0] = inf; root = 0; findroot(1, 0);
    work(1); 
    printf("%d\n", ans);
}
signed main() {
    freopen("a.in", "r", stdin);
    for(int t = read(); t; t--, solve());
    return 0;
}

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网