弱省互測#0 t2

題意

給定兩個字符串 A 和 B,求下面四個問題的答案:
1.在 A 的子串中,不是 B 的子串的字符串的數量。
2.在 A 的子串中,不是 B 的子序列的字符串的數量。
3.在 A 的子序列中,不是 B 的子串的字符串的數量。
4.在 A 的子序列中,不是 B 的子序列的字符串的數量。
其中子串是指本質不一樣的子串,不一樣的位置相同的串也只算一個串
|S|<=2000node

分析

構造倆自動機而後同時跑c++

題解

構造一個子序列自動機,再構造一個後綴自動機,而後從根依次轉移,記錄狀態上的信息,記憶化一下。ui

#include <bits/stdc++.h>
using namespace std;
const int mo=1e9+7, Lim=100005;
int nid;
struct node {
    node *c[26], *f;
    int len, s, id;
    bool flag;
    void init() {
        memset(c, 0, sizeof c);
        f=0;
        len=s=0;
        flag=0;
    }
}Po[Lim], *iT=Po, *root[2], *last[2], *rt[2];
node *newnode() {
    iT->init();
    return iT++;
}
void init() {
    root[0]=newnode();
    root[1]=newnode();
    last[0]=root[0];
    last[1]=root[1];
    rt[0]=newnode();
    rt[1]=newnode();
}
void add1(int who, int ch) {
    node *now=last[who], *x=newnode();
    last[who]=x;
    x->len=now->len+1;
    x->id=nid++;
    for(; now && !now->c[ch]; now=now->f) {
        now->c[ch]=x;
    }
    if(!now) {
        x->f=root[who];
        return;
    }
    node *y=now->c[ch];
    if(y->len==now->len+1) {
        x->f=y;
        return;
    }
    node *z=newnode();
    *z=*y;
    z->id=nid++;
    z->len=now->len+1;
    x->f=y->f=z;
    for(; now && now->c[ch]==y; now=now->f) {
        now->c[ch]=z;
    }
}
void cal(node *x) {
    if(x->flag) {
        return;
    }
    x->flag=1;
    x->s=1;
    for(int ch=0; ch<26; ++ch) {
        if(x->c[ch]) {
            cal(x->c[ch]);
            x->s+=x->c[ch]->s;
            if(x->s>=mo) {
                x->s-=mo;
            }
        }
    }
}
void build1(int who, char *s) {
    nid=1;
    for(; *s; ++s) {
        add1(who, *s-'a');
    }
    cal(root[who]); 
}
void build2(int who, char *s) {
    nid=1;
    static node *tc[26];
    memset(tc, 0, sizeof tc);
    for(; *s; --s) {
        node *now=newnode();
        now->id=nid++;
        for(int ch=0; ch<26; ++ch) {
            now->c[ch]=tc[ch];
        }
        tc[*s-'a']=now;
    }
    for(int ch=0; ch<26; ++ch) {
        rt[who]->c[ch]=tc[ch];
    }
    cal(rt[who]);
}
int vis[5005][5005];
int getans(node *x, node *y) {
    if(!x) {
        return 0;
    }
    if(!y) {
        return x->s;
    }
    if(vis[x->id][y->id]!=-1) {
        return vis[x->id][y->id];
    }
    int ret=0;
    for(int ch=0; ch<26; ++ch) {
        ret+=getans(x->c[ch], y->c[ch]);
        if(ret>=mo) {
            ret-=mo;
        }
    }
    return vis[x->id][y->id]=ret;
}
char s[2][2005], *it[2];
int main() {
    init();
    scanf("%s%s", s[0], s[1]);
    build1(0, s[0]);
    build1(1, s[1]);
    for(int i=0; i<2; ++i) {
        for(it[i]=s[i]; *(it[i]+1); ++it[i]);
    }
    build2(0, it[0]);
    build2(1, it[1]);
    memset(vis, -1, sizeof vis); printf("%d\n", getans(root[0], root[1]));
    memset(vis, -1, sizeof vis); printf("%d\n", getans(root[0], rt[1]));
    memset(vis, -1, sizeof vis); printf("%d\n", getans(rt[0], root[1]));
    memset(vis, -1, sizeof vis); printf("%d\n", getans(rt[0], rt[1]));
    return 0;
}
相關文章
相關標籤/搜索