P4052 [JSOI2007]文本生成器

链接

洛谷P4052

思路

显然可读文本数量等于总数量减去不可读的数量。先建出AC自动机,然后令 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示到达编号为 j j j 的结点的长度为 i i i 的不匹配串数量就可以了。由于一些单词可能是另一些的子串,所以 build 的时候不要忘了加 tr[now].cnt |= tr[tr[now].fail].cnt;

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 9;
const int maxm = 100 + 9;
const ll mod = 1e4 + 7;
struct tnode {
    int ch[26];
    int cnt, fail;
};
int n, m;
namespace AC {
tnode tr[maxn];
int tot;
void insert(const string &s) {
    int len = s.length(), now = 0;
    for (int i = 0; i < len; ++i) {
        int c = s[i] - 'A';
        if (!tr[now].ch[c])
            tr[now].ch[c] = ++tot;
        now = tr[now].ch[c];
    }
    tr[now].cnt++;
}
void build() {
    queue<int> q;
    for (int i = 0; i < 26; ++i) {
        if (tr[0].ch[i]) {
            tr[tr[0].ch[i]].fail = 0;
            q.push(tr[0].ch[i]);
        }
    }
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = 0; i < 26; ++i) {
            int &now = tr[u].ch[i];
            if (now) {
                tr[now].fail = tr[tr[u].fail].ch[i];
                tr[now].cnt |= tr[tr[now].fail].cnt;
                q.push(now);
            } else {
                now = tr[tr[u].fail].ch[i];
            }
        }
    }
}
};
ll ksm(ll b, ll k) {
    ll ret = 1;
    b %= mod;
    while (k) {
        if (k & 1)
            ret = ret * b % mod;
        b = b * b % mod;
        k /= 2;
    }
    return ret;
}
using namespace AC;
ll dp[maxm][maxn];
signed main() {
    cin >> n >> m;
    string s;
    for (int i = 1; i <= n; ++i) {
        cin >> s;
        insert(s);
    }
    build();
    ll ans = ksm(26, m);
    dp[0][0] = 1;
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j <= tot; ++j) {
            for (int k = 0; k < 26; ++k) {
                if (!tr[tr[j].ch[k]].cnt) {
                    dp[i + 1][tr[j].ch[k]] = (dp[i + 1][tr[j].ch[k]] + dp[i][j]) % mod;
                }
            }
        }
    }
    for (int i = 0; i <= tot; ++i) 
        ans = (ans - dp[m][i] + mod) % mod;
    cout << ans << '\n';
    return 0;
}
posted @ 2021-03-26 16:50  Theophania  阅读(75)  评论(0)    收藏  举报