【hdu2243】【AC自动机】【矩阵乘法】考研路茫茫——单词情结

来源:互联网 发布:闲鱼可以淘宝介入吗 编辑:程序博客网 时间:2024/06/04 19:54

首先利用集转化思想,将问题转化为求一个词根都不包含的单词有多少种。

可以想到将所有的词根建为AC自动,然后使用DP求解。

由于长度范围很大,可以使用矩阵乘法加速。

并且题目中要求的是“长度不超过L的”,所以要求sum= A ^ 1 + A ^ 2 + A ^ 3 + ...... + A ^L

所有情况tot = 26 ^ 1 + 26 ^ 2 + 26 ^ 3 + ..... + 26 ^ L

后ans = tot - sum

代码:

#include<cstdio>#include<cstring>using namespace std;const int maxn = 30; const int child_num = 26;int matcal[maxn];int sz,matnum;long long n,k;struct Matrix{unsigned long long v[maxn][maxn];int x,y;Matrix(){memset(v,0,sizeof(v));x = y = 0;}}mat;class ACAutumaton{public:int chd[maxn][child_num];int fail[maxn],val[maxn];int Q[maxn],ID[128];int cnt;void Reset(){memset(chd[0],0,sizeof(chd[0]));memset(fail,0,sizeof(fail));for(int i = 0;i < 26;i++)ID['a'+i] = i;sz = 1;}void Insert(char *a,int key){int p = 0;for(;*a; a++){int c = ID[*a];if(!chd[p][c]){memset(chd[sz],0,sizeof(chd[sz]));val[sz] = 0;chd[p][c] = sz++;}p = chd[p][c];}val[p] = key;}void Construct(){int *s = Q,*e = Q;for(int i = 0;i < child_num;i++){if(chd[0][i]){fail[ chd[0][i] ] = 0;*e ++ = chd[0][i];}}while(s != e){int u = *s++;for(int i = 0;i < child_num;i++){int &v = chd[u][i];if(v){*e ++ = v;fail[v] = chd[ fail[u] ][i];val[v] |= val[fail[v]];}else v = chd[ fail[u] ][i];}}}}AC;void init(){freopen("hdu2243.in","r",stdin);freopen("hdu2243.out","w",stdout);}void work(){memset(mat.v,0,sizeof(mat.v));memset(matcal,0,sizeof(matcal));matnum = 0;for(int i = 0;i < sz;i++)if(!AC.val[i])matcal[i] = ++matnum;mat.x = matnum;mat.y = matnum;for(int i = 0;i < sz;i++){if(!AC.val[i]){for(int j = 0;j < child_num;j++){if(!AC.val[AC.chd[i][j]])mat.v[matcal[i]][matcal[AC.chd[i][j]]]++;}}}}Matrix mtAdd(Matrix A,Matrix B){Matrix C;C.x = A.x;C.y = B.y;for(int i = 1;i <= A.x;i++){for(int j = 1;j <= B.y;j++){C.v[i][j] = A.v[i][j] + B.v[i][j];}}return C;}Matrix mtMul(Matrix A,Matrix B){if(!A.x || !A.y)return B;Matrix C;C.x = A.x;C.y = B.y;for(int i = 1;i <= A.x;i++){for(int j = 1;j <= B.y;j++){for(int k = 1;k <= A.y;k++){C.v[i][j] += A.v[i][k] * B.v[k][j];}}}return C;}Matrix mtPow(Matrix A,long long b){Matrix tmp = A,ret;while(b){if(b & 1)ret = mtMul(ret,tmp);tmp = mtMul(tmp,tmp);b >>= 1;}return ret;}Matrix mtCal(Matrix A,long long b){if(b == 1)return A;Matrix B = mtPow(A,(b + 1) / 2);Matrix C = mtCal(A,b / 2);if(b % 2 == 0)return mtAdd(mtMul(B,C),C);else return mtAdd(mtAdd(B,mtMul(C,B)),C);}unsigned long long quick_pow(long long a,long long b){unsigned long long tmp = a,ret = 1;while(b){if(b & 1)ret = ret * tmp;tmp = tmp * tmp;b >>= 1;}return ret;}unsigned long long calc(int p,long long b){if(b == 1)return p;unsigned long long tmp1 = quick_pow(p,(b + 1) / 2);unsigned long long tmp2 = calc(p,b / 2);if(b % 2 == 0)return (tmp1 * tmp2) + tmp2;else return tmp1 + tmp2 + tmp1 * tmp2;}void solve(){ AC.Construct();work();Matrix tmp = mtCal(mat,k);unsigned long long tot = calc(26,k),ans = 0;for(int i = 1;i <= matnum;i++){ans += tmp.v[1][i];}printf("%llu\n",tot - ans);}void readdata(){while(scanf("%lld%lld",&n,&k) != EOF){AC.Reset();char s[10];for(int i = 1;i <= n;i++){scanf("%s",s);AC.Insert(s,1);}solve();}}int main(){init();readdata();return 0;}


原创粉丝点击