hdu 2604 Queuing (Matrix)

本文介绍了一种解决 HDU 2604 题目的方法,该题目要求计算长度为 n 的不含特定子串的字符串数量。通过构建 AC 自动机并运用矩阵快速幂来高效解决问题。

http://acm.hdu.edu.cn/showproblem.php?pid=2604

  题意是找出长度为n的,不包含“fmf”或“fff”的字符串的个数。

  这题我是直接套用之前的ac自动机的模板的,构造出自动机,然后利用矩阵快速幂求出结果。当然,这题可以直接推出递推公式,然后再套入矩阵中。复杂度O(m^2 log n),其中m是矩阵大小,n是要求计算的长度。

代码如下:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 
  6 using namespace std;
  7 
  8 const int MS = 20;
  9 int CS = MS;
 10 int MOD = 30;
 11 
 12 struct Mat {
 13     int val[MS][MS];
 14     Mat(int u = 0) {
 15         for (int i = 0; i < CS; i++) {
 16             for (int j = 0; j < CS; j++) {
 17                 val[i][j] = 0;
 18             }
 19             val[i][i] = u % MOD;
 20         }
 21     }
 22     void print() {
 23         puts("Debug:");
 24         for (int i = 0; i < CS; i++) {
 25             for (int j = 0; j < CS; j++) {
 26                 cout << val[i][j] << ' ';
 27             }
 28             cout << endl;
 29         }
 30         puts("~~~~~~");
 31     }
 32 } Base, op;
 33 
 34 Mat operator + (Mat &a, Mat &b) {
 35     Mat ret;
 36     for (int i = 0; i < CS; i++) {
 37         for (int j = 0; j < CS; j++) {
 38             ret.val[i][j] = (a.val[i][j] + b.val[i][j]) % MOD;
 39         }
 40     }
 41     return ret;
 42 }
 43 
 44 Mat operator * (Mat &a, Mat &b) {
 45     Mat ret = Mat();
 46     for (int i = 0; i < CS; i++) {
 47         for (int k = 0; k < CS; k++) {
 48             if (a.val[i][k]) {
 49                 for (int j = 0; j < CS; j++) {
 50                     ret.val[i][j] += a.val[i][k] * b.val[k][j];
 51                     ret.val[i][j] %= MOD;
 52                 }
 53             }
 54         }
 55     }
 56     return ret;
 57 }
 58 
 59 Mat operator ^ (Mat &a, int p) {
 60     Mat t = a;
 61     Mat ret = Mat(1);
 62     while (p > 0) {
 63         if (p & 1) ret = ret * t;
 64         t = t * t;
 65         p >>= 1;
 66     }
 67     return ret;
 68 }
 69 
 70 const int kind = 2;
 71 const int N = 10;
 72 int root, cntNode;
 73 
 74 struct Node {
 75     int c[kind];
 76     int fail;
 77     bool end;
 78     void init() {
 79         memset(c, -1, sizeof(c));
 80         fail = -1;
 81         end = false;
 82     }
 83 } node[N];
 84 int Q[N], qh, qt;
 85 
 86 void init() {
 87     root = cntNode = 0;
 88     node[root].init();
 89 }
 90 
 91 void insert(char *s) {
 92     int p = root, idx;
 93     while (*s) {
 94         idx = (*s == 'f');
 95         if (node[p].c[idx] == -1) {
 96             node[++cntNode].init();
 97             node[p].c[idx] = cntNode;
 98         }
 99         p = node[p].c[idx];
100         s++;
101     }
102     node[p].end = true;
103 }
104 
105 void buildMat() {
106     op = Mat();
107     Base = Mat();
108     Base.val[0][0] = 1;
109     qh = qt = 1;
110     Q[qt++] = root;
111     while (qh < qt) {
112         int u = Q[qh++];
113         for (int i = 0; i < kind; i++) {
114             int c = node[u].c[i];
115             if (~c) {
116                 if (u == root) {
117                     node[c].fail = root;
118                 } else {
119                     node[c].fail = node[node[u].fail].c[i];
120                     if (node[node[c].fail].end) node[c].end = true;
121                 }
122                 Q[qt++] = c;
123             } else {
124                 if (u == root) {
125                     node[u].c[i] = root;
126                 } else {
127                     node[u].c[i] = node[node[u].fail].c[i];
128                 }
129             }
130         }
131     }
132     for (int i = 0; i < CS; i++) {
133         if (node[i].end) continue;
134         for (int j = 0; j < kind; j++) {
135             int t = node[i].c[j];
136             if (node[t].end) continue;
137             op.val[i][t]++;
138         }
139     }
140 }
141 
142 void PRE() {
143     char *str[2] = { "fmf", "fff"};
144     init();
145     insert(str[0]);
146     insert(str[1]);
147     CS = cntNode + 1;
148     buildMat();
149 }
150 
151 int main() {
152     int n;
153     PRE();
154 //    op.print();
155     while (cin >> n >> MOD) {
156         Base = op;
157         Base = Base ^ n;
158 //        Base.print();
159         int ans = 0;
160         for (int i = 0; i < CS; i++) {
161             ans += Base.val[0][i];
162             ans %= MOD;
163         }
164         cout << ans << endl;
165     }
166     return 0;
167 }
View Code

 

——written by Lyon

转载于:https://www.cnblogs.com/LyonLys/archive/2013/05/26/hdu_2604_Lyon.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值