1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > HDU 2243 考研路茫茫——单词情结(AC自动机 + 矩阵快速幂)题解

HDU 2243 考研路茫茫——单词情结(AC自动机 + 矩阵快速幂)题解

时间:2022-10-06 07:20:59

相关推荐

HDU 2243 考研路茫茫——单词情结(AC自动机 + 矩阵快速幂)题解

题意:找出所有长度不大于L的,包含至少一个模式串的主串的个数。

思路:和2778类似,但是这里求1~L所有长度的种数。所以我们只要求出来不包含的所有个数就行。

假设AC自动机上所有节点的邻接矩阵为A,那么答案为$\sum_{i=1}^n 26^i - \sum_{i=1}^n A^i$。

因为L有点大,那么我们可以直接用矩阵快速幂来求:

令$S_n = \sum_{i=1}^n 26^i ,T_n = \sum_{i=1}^n A^i$

$$ \left[ \begin{matrix} T_{n-1} & A \\ 0 & 0 \end{matrix} \right] * \left[ \begin{matrix} A & 0 \\ E & E \end{matrix} \right] = \left[ \begin{matrix} T_{n} & A \\ 0 & 0 \end{matrix} \right]$$

$$ \left[ \begin{matrix} S_{n-1} & 26 \\ 0 & 0 \end{matrix} \right] * \left[ \begin{matrix} 26 & 0 \\ 1 & 1 \end{matrix} \right] = \left[ \begin{matrix} S_{n} & 26 \\ 0 & 0 \end{matrix} \right]$$

求$T_n$的时候直接开一个大矩阵求就行了

代码:

#include<cmath>#include<set>#include<map>#include<queue>#include<cstdio>#include<vector>#include<cstring>#include <iostream>#include<algorithm>using namespace std;typedef long long ll;typedef unsigned long long ull;const int maxn = 30 + 5;const int M = 50 + 5;const ull seed = 131;const double INF = 1e20;const int MOD = 100000;int n;ll L;struct Mat{ull s[maxn * 2][maxn * 2];void init(){for(int i = 0; i < maxn * 2; i++)for(int j = 0; j < maxn * 2; j++)s[i][j] = 0;}};Mat mul(Mat &a, Mat &b, int tn){Mat t;t.init();for(int i = 0; i < tn; i++){for(int j = 0; j < tn; j++){for(int k = 0; k < tn; k++){t.s[i][j] = t.s[i][j] + a.s[i][k] * b.s[k][j];}}}return t;}Mat ppow(Mat a, ll b, int tn){Mat ret;ret.init();for(int i = 0; i < maxn * 2; i++) ret.s[i][i] = 1;while(b){if(b & 1) ret = mul(ret, a, tn);a = mul(a, a, tn);b >>= 1;}return ret;}struct Aho{struct state{int next[26];int fail, cnt;}node[maxn];int size;queue<int> q;void init(){size = 0;newtrie();while(!q.empty()) q.pop();}int newtrie(){memset(node[size].next, 0, sizeof(node[size].next));node[size].cnt = node[size].fail = 0;return size++;}void insert(char *s){int len = strlen(s);int now = 0;for(int i = 0; i < len; i++){int c = s[i] - 'a';if(node[now].next[c] == 0){node[now].next[c] = newtrie();}now = node[now].next[c];}node[now].cnt = 1;}void build(){node[0].fail = -1;q.push(0);while(!q.empty()){int u = q.front();q.pop();if(node[node[u].fail].cnt && u) node[u].cnt = 1; //都不能取for(int i = 0; i < 26; i++){if(!node[u].next[i]){if(u == 0)node[u].next[i] = 0;elsenode[u].next[i] = node[node[u].fail].next[i];}else{if(u == 0) node[node[u].next[i]].fail = 0;else{int v = node[u].fail;while(v != -1){if(node[v].next[i]){node[node[u].next[i]].fail = node[v].next[i];break;}v = node[v].fail;}if(v == -1) node[node[u].next[i]].fail = 0;}q.push(node[u].next[i]);}}}}ull query(){Mat A;A.init();for(int i = 0; i < size; i++){for(int j = 0; j < 26; j++){if(node[node[i].next[j]].cnt == 0){A.s[i][node[i].next[j]]++;}}}Mat a, b;a.init(), b.init();for(int i = 0; i < size; i++){for(int j = 0; j < size; j++){a.s[i][j] = a.s[i][j + size] = b.s[i][j] = A.s[i][j];}}for(int i = 0; i < size; i++){b.s[i + size][i] = b.s[i + size][i + size] = 1;}b = ppow(b, L - 1, 2 * size);a = mul(a, b, 2 * size);ull ret = 0;for(int i = 0; i < size; i++){if(node[i].cnt == 0) ret += a.s[0][i];}return ret;}}ac;char s[20];int main(){while(~scanf("%d%lld", &n, &L)){ull ans = 0;Mat a, b;a.init(), b.init();a.s[0][0] = a.s[0][1] = 26;b.s[0][0] = 26, b.s[1][0] = 1, b.s[1][1] = 1;b = ppow(b, L - 1, 4);a = mul(a, b, 4);ans = a.s[0][0];ac.init();while(n--){scanf("%s", s);ac.insert(s);}ac.build();ull ret = ac.query();cout << ans - ret << endl;}return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。