DNA Sequence POJ - 2778

DNA Sequence POJ - 2778

又被poj教育了一晚上, ll 取膜会t就离谱, 淦

题面

传送门

题解

先看数据, m <= 10 且 |s| <= 10, n <= 2e9

明显n是不可能线性了, 考虑字符串吧

这么小的数据量, 要去想用 tire 存

然后不出现这些串, 就是所求串在trie上没匹配

既然要匹配每个串, 那直接trie变成Ac自动机吧

然后无非就是在自动机上 next 乱走只要不走到字符串的 尾节点(或者当前失配能走到其他串的尾节点)

就合法, 就变成了有多少长度为 n 的路径条数, 那就是矩阵快速幂了

~~t了一晚上, 吐了, ll取膜复杂度这么高的吗~

struct Martrix { 
    int n, m;
	vector<VI> ma;
    Martrix(int N = 0, int M = 0) : n(N), m(M) { ma.resize(N, VI(M)); }
    Martrix operator*(const Martrix& a) {
        Martrix ans(n, a.m);
        rep(i, 0, n - 1) rep(j, 0, a.m - 1) {
			rep(k, 0, m - 1) ans.ma[i][j] = (ans.ma[i][j] + (ll)ma[i][k] * a.ma[k][j]) % mod;
		}
        return ans;
    }
};

struct AC {
    static const int N = 2e2 + 5, M = 4; //字符串总长度, 字符范围
    int trie[N][M], fail[N], q[N], tot;
    bool tag[N];
    void init() {
        rep(i, 0, M - 1) trie[0][i] = 0;
        tot = tag[0] = 0;
    }
    int newnode() {
        fail[++tot] = 0; memset(trie[tot], 0, sizeof trie[tot]);
        tag[tot] = 0;  return tot;
    }
    int getCH(char c) { return c == 'A' ? 0 : c == 'C' ? 1 : c == 'G' ? 2 : 3; }
    void insert(char* s) {
        int p = 0;
        for (int i = 0, ch = getCH(s[i]); s[i]; p = trie[p][ch], ch = getCH(s[++i]))
            if (!trie[p][ch]) trie[p][ch] = newnode();
        tag[p] = 1;
    }
    void build() {
        int head = 0, tail = -1;
        rep (i, 0, M - 1) if (trie[0][i]) q[++tail] = trie[0][i];
        for (int p = q[head]; head <= tail; p = q[++head])
            rep (i, 0, M - 1)
                if (trie[p][i])
                    fail[trie[p][i]] = trie[fail[p]][i], q[++tail] = trie[p][i], tag[trie[p][i]] |= tag[fail[trie[p][i]]];
                else trie[p][i] = trie[fail[p]][i];
    }
} ac;

const int N = 4e1 + 5, M = 123 + 5;
int n, m, _, k;
char s[15];

Martrix a, b;

void getMartrix() {
    a = Martrix(ac.tot + 1, ac.tot + 1); b = Martrix(ac.tot + 1, 1);
    rep(i, 0, ac.tot) {
        if (!ac.tag[i]) 
            rep(j, 0, 3) 
                if (!ac.tag[ac.trie[i][j]]) ++a.ma[i][ac.trie[i][j]];
        b.ma[i][0] = 1;
    }
}

Martrix qpow(Martrix a, ll b) {
    Martrix ans(a.n, a.m);
    rep(i, 0, a.n - 1) ans.ma[i][i] = 1;
    for (; b; b >>= 1, a = a * a)
        if (b & 1) ans = ans * a;
    return ans;
}

int main() {
    IOS; cin >> m >> n; ac.init();
    rep(i, 1, m) cin >> s, ac.insert(s);
    ac.build(); getMartrix();
    a = qpow(a, n) * b;
	cout << a.ma[0][0];
    return 0;
}
posted @ 2020-12-24 22:34  洛绫璃  阅读(55)  评论(0编辑  收藏  举报