E - Three strings

将三个串加进去,看每个节点在三个串中分别出现了多少次。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define PLI pair<LL, int>
#define ull unsigned long long
using namespace std;

const int N = 5e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;

int n, ans[N], len[3];
char s[3][N];

struct SuffixAutomaton {
    int cur, cnt, ch[N<<1][26], id[N<<1], fa[N<<1], dis[N<<1], sz[N<<1], c[N];
    int num[3][N<<1];
    SuffixAutomaton() {cur = cnt = 1;}
    void init() {
        for(int i = 1; i <= cnt; i++) {
            memset(ch[i], 0, sizeof(ch[i]));
            sz[i] = c[i] = dis[i] = fa[i] = 0;
        }
        cur = cnt = 1;
    }
    int extend(int p, int c) {
        cur = ++cnt; dis[cur] = dis[p]+1;
        for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = cur;
        if(!p) fa[cur] = 1;
        else {
            int q = ch[p][c];
            if(dis[q] == dis[p]+1) fa[cur] = q;
            else {
                int nt = ++cnt; dis[nt] = dis[p]+1;
                memcpy(ch[nt], ch[q], sizeof(ch[q]));
                fa[nt] = fa[q]; fa[q] = fa[cur] = nt;
                for(; ch[p][c]==q; p=fa[p]) ch[p][c] = nt;
            }
        }
        sz[cur] = 1;
        return cur;
    }
    void topo(int n) {
        for(int i = 1; i <= cnt; i++) c[dis[i]]++;
        for(int i = 1; i <= n; i++) c[i] += c[i-1];
        for(int i = cnt; i >= 1; i--) id[c[dis[i]]--] = i;
    }
    void solve() {
        for(int i = 0; i < 3; i++) {
            scanf("%s", s[i]); len[i] = strlen(s[i]);
            for(int j = 0, last = 1; j < len[i]; j++)
                last = extend(last, s[i][j]-'a');
        }
        for(int i = 0; i < 3; i++) {
            for(int j = 0, p = 1; j < len[i]; j++) {
                p = ch[p][s[i][j]-'a'];
                num[i][p]++;
            }
        }
        topo(max(len[0], max(len[1], len[2])));
        for(int i = cnt; i >= 1; i--)
            for(int j = 0; j < 3; j++)
                num[j][fa[id[i]]] += num[j][id[i]];
        for(int i = 2; i <= cnt; i++) {
            int ret = 1ll*num[0][i]*num[1][i]%mod*num[2][i]%mod;
            int mx = dis[i], mn = dis[fa[i]]+1;
            ans[mn] = (ans[mn] + ret) % mod;
            ans[mx+1] = (ans[mx+1]-ret+mod)%mod;
        }
        int Len = min(len[0], min(len[1], len[2]));
        for(int i = 1; i <= Len; i++) {
            ans[i] = (ans[i] + ans[i-1]) % mod;
            printf("%d ", ans[i]);
        }
        puts("");
    }
} sam;

int main() {
    sam.solve();
    return 0;
}

/*
*/

更多相关文章

  1. MySQL Cluster在线添加数据节点
  2. android 百度地图路线规划去掉节点图标
  3. android init进程分析 ueventd — 设备节点的创建、固件更新过
  4. android开发中调用系统中分享功能的方法

随机推荐

  1. Spring For Android初步
  2. H5 Web网页通过JS(JavaScript)脚本调用Andr
  3. 全新的Android通知栏,已抛弃setLatestEve
  4. 如何得到包含隐藏API的Android类库
  5. Android深入浅出之Audio 第一部分 AudioT
  6. android xml界面布局常用属性概括
  7. Android 众多的布局属性详解[转]
  8. Android发展史(Android各版本特性-技术篇)
  9. repo用法详解
  10. 【Android译文】Painless Thread