CCF 2015-09 最佳文章 解题报告
Jun 26, 2016 • 🍻 04min 10s read
🔖 acmAho-Corasick 自动机矩阵快速幂动态规划解题报告
问题简述
¶有
数据范围:
样例输入:
12343 15agvaagvagvagvagva
样例输出:
111
问题简析
¶先将
状态转移方程:
其中,
样例的状态图如下

其中,虚线为 fail 指针。上图中,
接下来就是重头戏了。我们可以构造一个
结合前面的状态转移方程有:
如果将
不难发现:
这和转移方程是对应的,这意味着:
等等,
可以通过
程序实现
¶solution.cpp
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138#include <algorithm>#include <cstdio>#include <cstring>#include <iostream>#include <queue>using namespace std;
typedef long long LL;const LL LNF = 0x3f3f3f3f3f3f3f3fLL;
struct Matrix { static const int MAXN = 100 + 10;
LL M[MAXN][MAXN];
void fill(LL val) { for (int i = 0; i < MAXN; ++i) for (int j = 0; j < MAXN; ++j) M[i][j] = val; }
friend Matrix operator*(const Matrix& A, const Matrix& B) { Matrix C; C.fill(-LNF); for (int i = 0; i < MAXN; ++i) for (int j = 0; j < MAXN; ++j) for (int k = 0; k < MAXN; ++k) C.M[i][j] = max(C.M[i][j], A.M[i][k] + B.M[k][j]); return C; }
static Matrix Power(Matrix A, LL X) { Matrix ans; ans.fill(-LNF); for (int i = 0; i < MAXN; ++i) ans.M[i][i] = 0; for (; X > 0; X >>= 1, A = A * A) if (X & 1) ans = ans * A; return ans; }
void show(int N = MAXN) const { for (int i = 0; i < N; ++i) printf("%6d ", i); printf("\n-------------------------------------------------------------\n"); for (int i = 0; i < N; ++i) { printf("%2d:|", i); for (int j = 0; j < N; ++j) printf("%6d|", M[i][j]); printf("\n"); } printf("-------------------------------------------------------------\n"); }};
struct AhoCorasick { static const int SIGMA_SIZ = 26; static const int MAX_NODES = 100 + 10; int ch[MAX_NODES][SIGMA_SIZ]; int val[MAX_NODES]; int fail[MAX_NODES]; int siz;
void init() { siz = 1; memset(ch[0], 0, sizeof ch[0]); }
int idx(const char c) const { return c - 'a'; }
void insert(const char* s) { int r = 0; for (; *s; ++s) { int c = idx(*s); if (!ch[r][c]) { memset(ch[siz], 0, sizeof ch[siz]); val[siz] = 0; ch[r][c] = siz++; } r = ch[r][c]; } ++val[r]; }
void calcFail() { static queue<int> Q; for (int c = 0; c < SIGMA_SIZ; ++c) { int o = ch[0][c]; if (o) fail[o] = 0, Q.push(o); } while (!Q.empty()) { int r = Q.front(); Q.pop(); for (int c = 0; c < SIGMA_SIZ; ++c) { int o = ch[r][c]; if (o) { int fo = fail[r]; for (; fo && !ch[fo][c]; fo = fail[fo]) ; fail[o] = ch[fo][c]; val[o] += val[fail[o]]; Q.push(o); } else { ch[r][c] = ch[fail[r]][c]; } } } }
void buildMatrix(Matrix& mat) { mat.fill(-LNF); for (int r = 0; r < siz; ++r) for (int c = 0; c < SIGMA_SIZ; ++c) mat.M[ch[r][c]][r] = val[ch[r][c]]; }};
Matrix mat;AhoCorasick ac;int N;LL M;char s[200];
int main() { ac.init(); scanf("%d%lld", &N, &M); for (int i = 0; i < N; ++i) { scanf("%s", s); ac.insert(s); } ac.calcFail(); ac.buildMatrix(mat); // for(int i=0; i < ac.siz; ++i) printf("%d, fail[%d]=%d\n", i, i, // ac.fail[i]); mat.show(ac.siz); mat = Matrix::Power(mat, M); LL ans = 0; for (int i = 0; i < Matrix::MAXN; ++i) ans = max(ans, mat.M[i][0]); printf("%lld\n", ans); return 0;}
Related
¶