首页 > 其他 > 详细

51nod1814 Clarke and string

时间:2019-10-13 09:22:34      阅读:103      评论:0      收藏:0      [点我收藏+]

[传送门]

直接想最暴力的做法就是正解了。
每次询问都把两个串的回文树建出来,然后再两棵树上同时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

 

51nod1814 Clarke and string

原文:https://www.cnblogs.com/Mrzdtz220/p/11664640.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!