51nod1814 Clarke and string

[传送门]

直接想最暴力的做法就是正解了。
每次询问都把两个串的回文树建出来,然后再两棵树上同时dfs,经过相同的节点答案就加一。遇到一个不存在的就退出。
再把询问记忆化一下就OK了。
复杂度是 $O(n \sqrt n)$
因为每次dfs的复杂度跟短的串的长度有关。
自己写给写T了。学习了下优秀写法。多开一个数组表示next是不是当前的next的。这样就不用每次都清数组了。

#include <bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;

const int N = 1e5 + 7;
const int sz = 26;

struct PAM {
    int s[N], fail[N], len[N];
    pii ne[N][sz];
    int n, tol, last, cnt;
    void init() {
        n = last = 0;
        tol = 1;
        s[0] = len[1] = -1;
        fail[0] = 1;
        ++cnt;
    }    
    inline int getid(int x) {
        while (s[n - len[x] - 1] != s[n]) x = fail[x];
        return x;
    }
    inline void extend(int c) {
        s[++n] = c;
        int cur = getid(last);
        if (ne[cur][c].se != cnt) {
            int k = getid(fail[cur]);
            fail[++tol] = ne[k][c].se == cnt ? ne[k][c].fi : 0;
            ne[cur][c] = pii(tol, cnt); len[tol] = len[cur] + 2;
        }  
        last = ne[cur][c].fi;
    }
} pam[2];

vector<char> s[N];
map<pii, int> mp;
char str[N];

int ans;

void dfs(int u, int v) {
    for (int i = 0; i < sz; i++) {
        if (pam[0].ne[u][i].se == pam[0].cnt && pam[1].ne[v][i].se == pam[1].cnt) {
            ans++;
            dfs(pam[0].ne[u][i].fi, pam[1].ne[v][i].fi);
        }
    }
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%s", str);
        int len = strlen(str);
        for (int j = 0; j < len; j++)
            s[i].push_back(str[j]);
    }
    int q;
    scanf("%d", &q);
    while (q--) {
        int a, b;
        scanf("%d%d", &a, &b);
        a ^= ans, b ^= ans;
        if (s[a].size() > s[b].size()) swap(a, b);
        if (mp.count(pii(a, b))) {
            printf("%d\n", mp[pii(a, b)]);
            continue;
        }
        pam[0].init(), pam[1].init();
        int len = s[a].size();
        for (int i = 0; i < len; i++)
            pam[0].extend(s[a][i] - 'a');
        len = s[b].size();
        for (int i = 0; i < len; i++)
            pam[1].extend(s[b][i] - 'a');
        ans = 0;
        dfs(0, 0); dfs(1, 1);
        printf("%d\n", mp[pii(a, b)] = ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/11664640.html