【后缀自动机】HDU 5343 MZL's Circle Zhou

通道

题意:从A,B分别取出子串X,Y,求多少种不同的X+Y

思路:

 

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAX_N = 200007;

typedef unsigned long long ll;

struct SAM {
    int val[MAX_N], fa[MAX_N], c[26][MAX_N];
    int tot, last;
    int which[MAX_N];
    inline int newNode(int step) {
        val[++tot] = step;
        fa[tot] = 0;
        for (int i = 0; i < 26; ++i) c[i][tot] = 0;
        return tot;
    }
    inline void extend(int k) {
        int p = last;
        int np = newNode(val[last] + 1);
        which[np] = k;
        while (p && !c[k][p]) c[k][p] = np, p = fa[p];
        if (!p) fa[np] = 1;
        else {
            int q = c[k][p];
            if (val[q] == val[p] + 1) fa[np] = q;
            else {
                int nq = newNode(val[p] + 1);
                which[nq] = k;
                for (int i = 0; i < 26; ++i) c[i][nq] = c[i][q];
                fa[nq] = fa[q]; 
                fa[q] = fa[np] = nq;
                while (p && c[k][p] == q) c[k][p] = nq, p = fa[p];
            }
        }
        last = np;
    }
    inline int add(int k) {
        extend(k);
    }
    inline void init() {
        tot = 0;
        last = newNode(0);
    }
} suf;

char A[MAX_N>>1], B[MAX_N>>1];
ll dp[26];

int main() {
    int T;
    scanf("%d", &T);
    while (T-- > 0) {
        suf.init();
        scanf("%s%s", A, B);
        int n = strlen(B);
        reverse(B, B + n);
        for (int i = 0; B[i]; ++i) suf.add(B[i] - 'a');
        memset(dp, 0, sizeof dp);
        for (int i = 1; i <= suf.tot; ++i) 
            dp[suf.which[i]] += suf.val[i] - suf.val[suf.fa[i]];
        suf.init(); 
        for (int i = 0; A[i]; ++i) suf.add(A[i] - 'a');
        ll ans = 0;
        for (int i = 1; i <= suf.tot; ++i) {
            for (int j = 0; j < 26; ++j) if (!suf.c[j][i]) {
                ans += dp[j] * (suf.val[i] - suf.val[suf.fa[i]]);
            }
            if (suf.fa[i]) ans += suf.val[i] - suf.val[suf.fa[i]];
        }
        printf("%I64u\n", ans + 1);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Rojo/p/4703344.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值