模板:

struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
bool symbol[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));symbol[] = false;}
int idx(char c)
{
return c - 'a';
} void insert(char * s)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
symbol[sz] = false;
ch[u][c] = sz++;
}
u = ch[u][c];
}
symbol[u] = true;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
if (symbol[fail[r]]) symbol[r] = true;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
// cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
symbol[] = false;
} Matrix build_mat()
{
Matrix ret = Matrix(sz + );
for (int i = ; i < sz ; i++)
for (int j = ; j < SIGMA_SIZE ; j++)
if (symbol[i] == false && !symbol[ch[i][j]])
ret.mat[i][ch[i][j]]++;
for (int i = ; i <= sz ; i++)
ret.mat[i][sz] = ;
return ret;
}
}src;

HDU 2222 Keywords Search

找出主串中有多少个模式串出现

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
int ans;
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int cnt[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {return c - 'a';} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
cnt[u]++;
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 int fail[MAXNNODE],last[MAXNNODE];
int get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
ans += cnt[j];
cnt[j] = ;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
memset(cnt,false,sizeof(cnt));
}
}src;
int N;
char input[];
char tag[];
int main()
{
//freopen("sample.txt","r",stdin);
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&N);
gets(input);
src.init();
ans = ;
for (int i = ; i < N; i++)
{
gets(input);
src.insert(input,i + );
}
scanf("%s",tag);
src.get_fail();
src.Find(tag);
printf("%d\n",ans);
}
return ;
}

HDU 2896 病毒侵袭

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
vector<int>ans;
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {return c;} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
} val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 int fail[MAXNNODE],last[MAXNNODE];
void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
ans.push_back(val[j]);
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
//memset(cnt,false,sizeof(cnt));
}
}src;
char tmp[];
int N,M;
char tag[];
int main()
{
//freopen("sample.txt","r",stdin);
while (scanf("%d",&N) != EOF)
{
src.init();
for (int i = ; i <= N; i++)
{
scanf("%s",tmp);
src.insert(tmp,i);
}
src.get_fail();
scanf("%d",&M);
int ret = ;
for (int i = ; i <= M; i++)
{
ans.clear();
scanf("%s",tag);
src.Find(tag);
if (ans.size() == ) continue;
ret++;
printf("web %d:",i);
sort(ans.begin(),ans.end());
int k = unique(ans.begin(),ans.end()) - ans.begin();
for (int i = ; i < k ; i++)
printf(" %d",ans[i]);
putchar('\n');
}
printf("total: %d\n",ret);
}
return ;
}

HDU 3065 病毒侵袭持续中

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
int cnt[MAXNNODE];
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {return c - 'A';} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
}
}src;
char input[][];
char word[];
int N;
int main()
{
while (scanf("%d",&N) != EOF)
{
memset(cnt,,sizeof(cnt));
src.init();
for (int i = ; i <= N ; i++)
{
scanf("%s",input[i]);
src.insert(input[i],i);
}
src.get_fail();
scanf("%s",word);
src.Find(word);
for (int i = ; i <= N ; i++)
{
if (cnt[i])
printf("%s: %d\n",input[i],cnt[i]);
}
}
return ;
}

ZOJ 3430 Detect the Virus

题意:给出n个编码后的模板串,然后有M次询问,每次询问输入一个编码后的文本串,问在编码前,有多少个模板串在文本串中出现过。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int SIGMA_SIZE = ;
const int MAXNNODE = ;
vector<int>ret;
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
// int idx(char c) {return c;} void insert(int * s,int n,int v)
{
int u = ;
for (int i = ; i < n ; i++)
{
int c = s[i];
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
ret.push_back(val[j]);
print(last[j]);
}
} void Find(int * T,int n)
{
int j = ;
for (int i = ; i < n ; i++)
{
int c = T[i];
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
}
}src; int getid(char ch) {
if (isupper(ch)) return ch - 'A';
if (islower(ch)) return ch - 'a' + ;
if (isdigit(ch)) return ch - '' + ;
if (ch == '+') return ;
return ;
} int str[];
char word[];
int bit[ * ];
int decode(char * s) {
int top = ,res[];
int len = strlen(s);
for (int i = ; i < len ; i++) {
if (s[i] != '=') {
int idx = getid(s[i]);
for (int j = ; j >= ; j--) {
res[j] = idx & ;
idx >>= ;
}
for (int j = ; j < ; j++) {
bit[top++] = res[j];
}
}
else top -= ;
}
int x = ,tot = ;
for (int i = ; i < top ;) {
x = ;
for (int j = ; j < ; j++)
x = x * + bit[i++];
str[tot++] = x;
}
return tot;
} int main() {
int N,M;
while (scanf("%d",&N) != EOF) {
src.init();
for (int i = ; i <= N ; i++) {
scanf("%s",word);
int length = decode(word);
src.insert(str,length,i);
}
src.get_fail();
scanf("%d",&M);
while (M--) {
ret.clear();
scanf("%s",word);
int length = decode(word);
src.Find(str,length);
sort(ret.begin(),ret.end());
int cnt = unique(ret.begin(),ret.end()) - ret.begin();
printf("%d\n",cnt);
}
puts("");
}
return ;
}

POJ 2778 DNA Sequence

题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列。(仅含A,T,C,G四个字符)

复制一下别人的题解

这个和矩阵有什么关系呢???
•上图是例子{“ACG”,”C”},构建trie图后如图所示,从每个结点出发都有4条边(A,T,C,G)
•从状态0出发走一步有4种走法:
  –走A到状态1(安全);
  –走C到状态4(危险);
  –走T到状态0(安全);
  –走G到状态0(安全);
•所以当n=1时,答案就是3
•当n=2时,就是从状态0出发走2步,就形成一个长度为2的字符串,只要路径上没有经过危险结点,有几种走法,那么答案就是几种。依此类推走n步就形成长度为n的字符串。
•建立trie图的邻接矩阵M:

2 1 0 0 1

2 1 1 0 0

1 1 0 1 1

2 1 0 0 1

2 1 0 0 1

M[i,j]表示从结点i到j只走一步有几种走法。

那么M的n次幂就表示从结点i到j走n步有几种走法。

注意:危险结点要去掉,也就是去掉危险结点的行和列。结点3和4是单词结尾所以危险,结点2的fail指针指向4,当匹配”AC”时也就匹配了”C”,所以2也是危险的。

矩阵变成M:

2 1

2 1

计算M[][]的n次幂,然后 Σ(M[0,i]) mod 100000 就是答案。

由于n很大,可以使用二分来计算矩阵的幂

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
const LL MOD = ;
struct Matrix {
LL mat[MAXNNODE][MAXNNODE];
int n;
Matrix(){}
Matrix(int sz) {
n = sz;
for (int i = ; i < n ; i++)
for (int j = ; j < n ; j++) mat[i][j] = ;
} Matrix operator * (const Matrix &b) const{
Matrix ret = Matrix(n);
for (int i = ; i < n ; i++)
for (int j = ; j < n ; j++)
for (int k = ; k < n ; k++)
ret.mat[i][j] = (ret.mat[i][j] + mat[i][k] * b.mat[k][j]) % MOD;
return ret;
}
}; LL pow_mod(LL x,int cnt) {
LL ret = ;
while (cnt) {
if (cnt & ) ret = ret * x;
x = x * x % MOD;
cnt >>= ;
}
return ret;
} Matrix mat_pow(Matrix in,LL cnt) {
Matrix ret = Matrix(in.n);
Matrix x = in;
for (int i = ; i < ret.n ; i++) ret.mat[i][i] = ;
while (cnt) {
if (cnt & 1LL) ret = ret * x;
x = x * x;
cnt >>= 1LL;
}
return ret;
} struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
bool symbol[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));symbol[] = false;}
int idx(char c)
{
if (c == 'A') return ;
if (c == 'T') return ;
if (c == 'C') return ;
return ;
} void insert(char * s)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
symbol[sz] = false;
ch[u][c] = sz++;
}
u = ch[u][c];
}
symbol[u] = true;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
if (symbol[fail[r]]) symbol[r] = true;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
// cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
symbol[] = false;
} Matrix build_mat()
{
Matrix ret = Matrix(sz);
for (int i = ; i < sz ; i++)
for (int j = ; j < SIGMA_SIZE ; j++)
if (symbol[i] == false && !symbol[ch[i][j]])
ret.mat[i][ch[i][j]]++;
return ret;
}
}src; int main() {
LL M,N;
char tmp[];
while (scanf("%I64d%I64d",&M,&N) != EOF) {
src.init();
for (int i = ; i < M ; i++) {
scanf("%s",tmp);
src.insert(tmp);
}
src.get_fail();
Matrix cur = src.build_mat();
/* for (int i = 0 ; i < cur.n ; i++){
for (int j = 0 ; j < cur.n ; j++)
printf("%I64d ",cur.mat[i][j]);
puts("");
}*/
// Matrix ret = cur * cur * cur;
Matrix ret = mat_pow(cur,N);
/* for (int i = 0 ; i < cur.n ; i++){
for (int j = 0 ; j < cur.n ; j++)
printf("%I64d ",ret.mat[i][j]);
puts("");
}*/
LL ans = ;
for (int i = ; i < src.sz ; i++)
ans = (ans + ret.mat[][i]) % MOD;
printf("%I64d\n",ans);
}
return ;
}

HDU 2243 考研路茫茫――单词情结

这题的意思是,给你n个长度不超过5的字符串,求有多少个长度为至少为L的字符串,里面至少包含n个字符串中的一个。

这题和求DNA片段的差不多啦,只不过L的条件有点变化。

POJ2778 是求长度为n,不包含模式串。

假设矩阵A里储存着字符间的可行转移,那么A^L就代表了长度为L的不包含n个字符串中任何一个的个数。

最终的答案就是26^1+26^2+......+26^L减去A^1+A^2+....+A^L

矩阵A可以用ac自动机维护一个跳转表得到。接下来就是考虑如何快速的求得A^1+A^2+....+A^L了。

根据矩阵的性质

|A  ,  1|                 |A^n , 1+A^1+A^2+....+A^(n-1)|

|0  ,  1| 的n次方等于|0     ,                                       1|

利用POJ 2778 的方式构建A

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ULL unsigned long long
#define LL unsigned long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
const LL MOD = ;
struct Matrix {
ULL mat[MAXNNODE][MAXNNODE];
int n;
Matrix(){}
Matrix(int sz) {
n = sz;
for (int i = ; i < n ; i++)
for (int j = ; j < n ; j++) mat[i][j] = ;
} Matrix operator * (const Matrix &b) const{
Matrix ret = Matrix(n);
for (int i = ; i < n ; i++)
for (int j = ; j < n ; j++)
for (int k = ; k < n ; k++)
ret.mat[i][j] = (ret.mat[i][j] + mat[i][k] * b.mat[k][j]);
return ret;
}
}; LL pow_mod(LL x,int cnt) {
LL ret = ;
while (cnt) {
if (cnt & ) ret = ret * x;
x = x * x % MOD;
cnt >>= ;
}
return ret;
} Matrix mat_pow(Matrix in,LL cnt) {
Matrix ret = Matrix(in.n);
Matrix x = in;
for (int i = ; i < ret.n ; i++) ret.mat[i][i] = ;
while (cnt) {
if (cnt & 1LL) ret = ret * x;
x = x * x;
cnt >>= 1LL;
}
return ret;
} struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
bool symbol[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));symbol[] = false;}
int idx(char c)
{
return c - 'a';
} void insert(char * s)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
symbol[sz] = false;
ch[u][c] = sz++;
}
u = ch[u][c];
}
symbol[u] = true;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
if (symbol[fail[r]]) symbol[r] = true;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
// cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
symbol[] = false;
} Matrix build_mat()
{
Matrix ret = Matrix(sz + );
for (int i = ; i < sz ; i++)
for (int j = ; j < SIGMA_SIZE ; j++)
if (symbol[i] == false && !symbol[ch[i][j]])
ret.mat[i][ch[i][j]]++;
for (int i = ; i <= sz ; i++)
ret.mat[i][sz] = ;
return ret;
}
}src; int main() {
LL M,N;
char tmp[];
while (scanf("%I64d%I64d",&M,&N) != EOF) {
src.init();
for (int i = ; i < M ; i++) {
scanf("%s",tmp);
src.insert(tmp);
}
src.get_fail();
Matrix cur = src.build_mat();
/* for (int i = 0 ; i < cur.n ; i++){
for (int j = 0 ; j < cur.n ; j++)
printf("%I64d ",cur.mat[i][j]);
puts("");
}*/
// Matrix ret = cur * cur * cur;
Matrix ret = mat_pow(cur,N);
/* for (int i = 0 ; i < cur.n ; i++){
for (int j = 0 ; j < cur.n ; j++)
printf("%I64d ",ret.mat[i][j]);
puts("");
}*/
ULL ans = ;
for (int i = ; i <= src.sz ; i++)
ans = (ans + ret.mat[][i]);
ans--; Matrix t = Matrix();
t.mat[][] = ;
t.mat[][] = t.mat[][] = ;
t = mat_pow(t,N);
ULL res = t.mat[][] + t.mat[][];
// << res << endl;
res--;
printf("%I64u\n",res - ans);
}
return ;
}

POJ 1625 Censored!

题意:给出包含n个可见字符的字符集,以下所提字符串均由该字符集中的字符构成。给出p个长度不超过10的字符串,求长为m且不包含上述p个字符串的字符串有多少个。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
map<char,int>mp;
struct Matrix
{
int mat[][];
int n;
Matrix(){}
Matrix(int sz)
{
n = sz;
for (int i = ; i < n ; i++)
for (int j = ; j < n ; j++) mat[i][j] = ;
}
}mt; const int numlen = ;
const int MAXNNODE = * ;
const int SIGMA_SIZE = ;
int N,M,P,cas;
struct bign {
int len, s[numlen];
bign() {
memset(s, , sizeof(s));
len = ;
}
bign(int num) { *this = num; }
bign(const char *num) { *this = num; }
bign operator = (const int num) {
char s[numlen];
sprintf(s, "%d", num);
*this = s;
return *this;
}
bign operator = (const char *num) {
len = strlen(num);
while(len > && num[] == '') num++, len--;
for(int i = ;i < len; i++) s[i] = num[len-i-] - '';
return *this;
} void deal() {
while(len > && !s[len-]) len--;
} bign operator + (const bign &a) const {
bign ret;
ret.len = ;
int top = max(len, a.len) , add = ;
for(int i = ;add || i < top; i++) {
int now = add;
if(i < len) now += s[i];
if(i < a.len) now += a.s[i];
ret.s[ret.len++] = now%;
add = now/;
}
return ret;
}
bign operator - (const bign &a) const {
bign ret;
ret.len = ;
int cal = ;
for(int i = ;i < len; i++) {
int now = s[i] - cal;
if(i < a.len) now -= a.s[i];
if(now >= ) cal = ;
else {
cal = ; now += ;
}
ret.s[ret.len++] = now;
}
ret.deal();
return ret;
}
bign operator * (const bign &a) const {
bign ret;
ret.len = len + a.len;
for(int i = ;i < len; i++) {
for(int j = ;j < a.len; j++)
ret.s[i+j] += s[i]*a.s[j];
}
for(int i = ;i < ret.len; i++) {
ret.s[i+] += ret.s[i]/;
ret.s[i] %= ;
}
ret.deal();
return ret;
} bign operator * (const int num) {
// printf("num = %d\n", num);
bign ret;
ret.len = ;
int bb = ;
for(int i = ;i < len; i++) {
int now = bb + s[i]*num;
ret.s[ret.len++] = now%;
bb = now/;
}
while(bb) {
ret.s[ret.len++] = bb % ;
bb /= ;
}
ret.deal();
return ret;
} bign operator / (const bign &a) const {
bign ret, cur = ;
ret.len = len;
for(int i = len-;i >= ; i--) {
cur = cur*;
cur.s[] = s[i];
while(cur >= a) {
cur -= a;
ret.s[i]++;
}
}
ret.deal();
return ret;
} bign operator % (const bign &a) const {
bign b = *this / a;
return *this - b*a;
} bign operator += (const bign &a) { *this = *this + a; return *this; }
bign operator -= (const bign &a) { *this = *this - a; return *this; }
bign operator *= (const bign &a) { *this = *this * a; return *this; }
bign operator /= (const bign &a) { *this = *this / a; return *this; }
bign operator %= (const bign &a) { *this = *this % a; return *this; } bool operator < (const bign &a) const {
if(len != a.len) return len < a.len;
for(int i = len-;i >= ; i--) if(s[i] != a.s[i])
return s[i] < a.s[i];
return false;
}
bool operator > (const bign &a) const { return a < *this; }
bool operator <= (const bign &a) const { return !(*this > a); }
bool operator >= (const bign &a) const { return !(*this < a); }
bool operator == (const bign &a) const { return !(*this > a || *this < a); }
bool operator != (const bign &a) const { return *this > a || *this < a; } string str() const {
string ret = "";
for(int i = ;i < len; i++) ret = char(s[i] + '') + ret;
return ret;
}
};
istream& operator >> (istream &in, bign &x) {
string s;
in >> s;
x = s.c_str();
return in;
}
ostream& operator << (ostream &out, const bign &x) {
out << x.str();
return out;
} bign dp[][]; struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {return mp[c];} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
val[r] |= val[fail[r]];
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
//cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
} Matrix build_mat()
{
Matrix ret = Matrix(sz);
for (int i = ; i < sz ; i++)
{
for (int j = ; j < N ; j++)
if (val[ch[i][j]] == false)
ret.mat[i][ch[i][j]]++;
}
return ret;
} void slove()
{
int cur = ;
dp[cur][] = ;
for (int i = ; i < sz ; i++)
dp[cur][i] = ;
for (int i = ; i < M ; i++)
{
cur ^= ;
for (int j = ; j < sz ; j++) dp[cur][j] = ;
for (int j = ; j < sz ; j++)
{
for (int k = ; k < sz ; k++)
if (mt.mat[j][k] > )
dp[cur][k] = dp[cur][k] + dp[cur ^ ][j] * mt.mat[j][k];
}
}
bign ret = "";
for (int i = ; i < sz ; i++)
ret = ret + dp[cur][i];
cout << ret << endl;
}
}src;
char str[];
int main()
{
// freopen("sample.txt","r",stdin);
while (scanf("%d%d%d",&N,&M,&P) != EOF)
{
mp.clear();
gets(str);
cas = ;
gets(str);
int len = strlen(str);
for (int i = ; i < len ; i++)
mp[str[i]] = cas++;
src.init();
for (int i = ; i < P; i++)
{
gets(str);
src.insert(str,);
}
src.get_fail();
mt = src.build_mat();
src.slove();
}
return ;
}

HDU 2825 Wireless Password

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
const int MOD = ;
int N,M,K;
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int dp[][MAXNNODE][ << ];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {return c - 'a';} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 int fail[MAXNNODE],last[MAXNNODE];
void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
val[r] |= val[fail[r]];
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
// val[u] |= val[fail[u]];
}
}
} void print(int j)
{
if (j)
{ print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
// memset(cnt,false,sizeof(cnt));
} int calcu(int n,int sta,int num)
{
memset(dp[],,sizeof(dp[]));
int cur = ,nxt;
dp[][][] = ;
while (n--)
{
nxt = - cur;
memset(dp[nxt],,sizeof(dp[nxt]));
for (int i = ; i < sz ; i++)
for (int j = ; j < sta ; j++)
{
if (dp[cur][i][j] == ) continue;
for (int k = ; k < SIGMA_SIZE ; k++)
{
int tmp = ch[i][k];
int nextsta = (j | (val[tmp]));
dp[nxt][tmp][nextsta] = (dp[nxt][tmp][nextsta] + dp[cur][i][j]) % MOD;
}
}
cur = nxt;
}
int ret = ;
for (int j = ; j < sta ; j++)
{
int cnt = ;
for (int i = ; i < N; i++)
if (j & ( << i)) cnt++;
if (cnt >= K)
{
for (int t = ; t < sz ; t++)
ret = (ret + dp[cur][t][j]) % MOD;
}
}
return ret;
}
}src;
int main()
{
//freopen("sample.txt","r",stdin);
while (scanf("%d%d%d",&N,&M,&K) != EOF)
{
if (N == && M == && K == ) break;
src.init();
for (int i = ; i < M; i++)
{
char tmp[];
scanf("%s",tmp);
src.insert(tmp, << i);
}
src.get_fail();
printf("%d\n",src.calcu(N, << M,K));
}
return ;
}

HDU 2296 Ring

题目:给出m个模式串,每个串有一定的分值,构造一个长度不超过n的串,使得分值最大,输出长度最小,字典序最小的串

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
const int INF = 0x3f3f3f3f;
int N,M;
int h[MAXNNODE];
char res[][MAXNNODE][]; bool cmp(char * s,char * t)
{
int len1 = strlen(s);
int len2 = strlen(t);
if (len1 != len2) return len1 < len2;
return strcmp(s,t) < ;
} struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
LL dp[][MAXNNODE];
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {return c - 'a';} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
// printf("%d %d\n",u,v);
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
// cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
} void calcu()
{
for (int i = ; i <= N ; i++)
for (int j = ; j < sz ; j++) dp[i][j] = -INF;
dp[][] = ;
strcpy(res[][],"");
char ret[];
strcpy(ret,"");
int MAX = ;
char tmp[];
for (int i = ; i < N ; i++)
{
for (int j = ; j < sz ; j++)
{
if (dp[i][j] < ) continue;
strcpy(tmp,res[i][j]);
int len = strlen(tmp);
for (int k = ; k < SIGMA_SIZE ; k++)
{
int nxt = ch[j][k];
tmp[len] = k + 'a';
tmp[len + ] = '\0';
//len++;
int value = dp[i][j];
if (val[nxt]) value += h[val[nxt]];
// if (value != 0) printf("%s %d\n",tmp);
if (dp[i + ][nxt] < value || (dp[i + ][nxt] == value && cmp(tmp,res[i + ][nxt])))
{
dp[i + ][nxt] = value;
strcpy(res[i + ][nxt],tmp);
if (value > MAX || (value == MAX && cmp(tmp,ret)))
{
MAX = value;
strcpy(ret,tmp);
}
}
}
}
}
// printf("%d\n",MAX);
printf("%s\n",ret);
}
}src; int main()
{
int T;
char buf[];
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&N,&M);
src.init();
for (int i = ; i < M ; i++)
{
scanf("%s",buf);
src.insert(buf,i + );
}
for (int i = ; i <= M ; i++) scanf("%d",&h[i]);
src.get_fail();
src.calcu();
}
return ;
}

HDU 2457 DNA repair

题目:给出一些不合法的模式DNA串,给出一个原串,问最少需要修改多少个字符,使得原串中不包含非法串

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c)
{
if (c == 'A') return ;
if (c == 'G') return ;
if (c == 'C') return ;
if (c == 'T') return ;
} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
if (val[fail[r]])
val[r] = true;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
//cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
}
}src;
int dp[][];
int N;
char str[];
int main()
{
// freopen("sample.txt","r",stdin);
int kase = ;
while (scanf("%d",&N) != EOF)
{
if (N == ) break;
src.init();
memset(dp,-,sizeof(dp));
for (int i = ; i < N; i++)
{
scanf("%s",str);
src.insert(str,);
}
src.get_fail();
scanf("%s",str + );
int len = strlen(str + );
dp[][] = ;
for (int i = ; i < len ; i++)
{
for (int j = ; j < src.sz ; j++)
{
if (dp[i][j] == -) continue;
int idx = src.idx(str[i + ]);
for (int k = ; k < ; k++)
{
int add = ;
if (k != idx) add = ;
if (src.val[src.ch[j][k]]) continue;
if (dp[i + ][src.ch[j][k]] == -) dp[i + ][src.ch[j][k]] = dp[i][j] + add;
else dp[i + ][src.ch[j][k]] = min(dp[i + ][src.ch[j][k]],dp[i][j] + add);
}
}
}
int ret = INT_MAX;
for (int i = ; i < src.sz ; i++)
{
if (dp[len][i] == -) continue;
ret = min(ret,dp[len][i]);
}
printf("Case %d: %d\n",kase++,ret == INT_MAX ? - : ret);
}
return ;
}

ZOJ 3228 Searching the String

计算可重叠不可重叠字串出现在主串的次数

可重叠就是裸地AC自动机。

不可重叠,记录字典树上每个点的深度,没匹配到一个模式串,记录一下位置,

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
const int INF = 0x3f3f3f3f;
int pos[MAXNNODE / ],N;
char str[MAXNNODE / ]; struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int depth[MAXNNODE],pre[MAXNNODE];
int cnt[MAXNNODE][];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {return c - 'a';} int insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
depth[sz] = i + ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] += v;//最后的叶子节点给与信息v
return u;
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int i,int j)
{
if (j)
{
// printf("%d\n",val[j]);
cnt[j][]++;
if (i - pre[j] >= depth[j])
{
cnt[j][]++;
pre[j] = i;
}
print(i,last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(i,j);
else if (last[j]) print(i,last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
memset(pre,-,sizeof(pre));
memset(cnt,,sizeof(cnt));
memset(val,,sizeof(val));
}
}src; int flag[MAXNNODE / ];
int main()
{
int kase = ;
while (scanf("%s",str) != EOF)
{
scanf("%d",&N);
src.init();
for (int i = ; i < N ; i++)
{
char tmp[];
scanf("%d%s",&flag[i],tmp);
pos[i] = src.insert(tmp,);
}
src.get_fail();
src.Find(str);
printf("Case %d\n",kase++);
for (int i = ; i < N ; i++)
printf("%d\n",src.cnt[pos[i]][flag[i]]);
puts("");
}
return ;
}

HDU 3247  Resource Archiver

题目:给出n个资源,m个病毒,将资源串拼接成一个串,必须包含所有的资源串,可以重叠,但是不能包含病毒

问最小的长度为多少

所有的资源串和病毒串都放在Trie树里建立起来,当然作上相应的标记。然后建立fail指针之后

从资源串的结尾出发,BFS,记录能到达其它资源串结尾的步数。得到所有资源串结尾状态的距离邻接阵。

之后是状态压缩DP

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
const int INF = 0x3f3f3f3f;
int pos[];
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int state[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {if (c == '') return ; return ;} void insert(char * s,bool v,int id = -)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
state[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
if (!v)
{
pos[id] = u;
state[u] |= ( << id);
//printf("%d %d\n",u,state[u]);
}
val[u] = val[u] || v;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
val[r] |= val[fail[r]]; //use in dp problem
state[r] |= state[fail[r]];
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
//cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
memset(val,,sizeof(val));
memset(state,,sizeof(state));
}
}src; int dist[][MAXNNODE];
char str[];
int length[];
int dp[][]; void bfs(int id,int st)
{
//printf("%d %d\n",id,st);
for (int i = ; i < src.sz ; i++) dist[id][i] = INF;
dist[id][st] = ;
queue<int>q;
q.push(st);
while (!q.empty())
{
int u = q.front();
q.pop();
int v = src.ch[u][];
if (!src.val[v] && dist[id][v] == INF)
{
dist[id][v] = dist[id][u] + ;;
q.push(v);
}
v = src.ch[u][];
if (!src.val[v] && dist[id][v] == INF)
{
dist[id][v] = dist[id][u] + ;
q.push(v);
}
}
} void calcu(int n)
{
int limit = ( << n);
for (int i = ; i <= n ; i++)
for (int j = ; j < limit ; j++) dp[i][j] = INF;
for (int i = ; i < n ; i++)
dp[i][ << i] = length[i];
for (int i = ; i < limit ; i++)
{
for (int j = ; j < n ; j++)
{
if ((i & ( << j)) && dp[j][i] != INF)
{
for (int k = ; k < n ; k++)
{
int nxt = i | src.state[pos[k]];
dp[k][nxt] = min(dp[k][nxt],dp[j][i] + dist[j][pos[k]]);
}
}
}
}
int ret = INF;
for (int i = ; i < n ; i++)
ret = min(ret,dp[i][limit - ]);
printf("%d\n",ret);
} int main()
{
int N,M;
while (scanf("%d%d",&N,&M) != EOF)
{
if (N == && M == ) break;
src.init();
memset(length,,sizeof(length));
for (int i = ; i < N ; i++)
{
scanf("%s",str);
length[i] = strlen(str);
src.insert(str,false,i);
}
for (int i = ; i < M ; i++)
{
scanf("%s",str);
src.insert(str,true);
}
src.get_fail();
// printf("%d\n",src.sz);
// for (int i = 0 ; i < 9 ; i++)printf("%d %d\n",i,src.val[i]);
for (int i = ; i < N ; i++) bfs(i,pos[i]);
calcu(N);
}
return ;
}

ZOJ 3494 BCD CODE

题目:给出一些模式串,给出一个范围[A,B],求出区间内有多少个数,写成BCD之后,不包含模式串

使用AC自动机,得到bcd[i][j]表示状态i,加了数字j以后到达的状态,为-1表示不能转移

然后就是数位DP了

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c) {return c - '';} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
if (val[fail[r]]) val[r] = ;
//val[r] += val[fail[r]]; use in dp problem
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
// cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
memset(val,,sizeof(val));
}
}src; int bcd[MAXNNODE][];
int trans(int pre,int num)
{
if (src.val[pre]) return -;
int cur = pre;
for (int i = ; i >= ; i--)
{
if (src.val[src.ch[cur][(num >> i) & ]]) return -;
cur = src.ch[cur][(num >> i) & ];
}
return cur;
} void init()
{
for (int i = ; i < src.sz ; i++)
for (int j = ; j < ; j++)
bcd[i][j] = trans(i,j);
} const int MOD = ;
LL dp[][MAXNNODE];
int digit[]; LL dfs(int length,int s,bool ismax,bool zero)
{
if (length == ) return ;
if (!ismax && dp[length][s] >= ) return dp[length][s];
LL ans = ;
if (length > && zero)
{
ans += dfs(length - ,s,ismax && digit[length] == ,true);
ans %= MOD;
}
else
{
if (bcd[s][] != -)
{
ans += dfs(length - ,bcd[s][],ismax && digit[length] == ,false);
ans %= MOD;
}
}
int limit = ismax ? digit[length] : ;
for (int i = ; i <= limit ; i++)
{
if (bcd[s][i] != -)
{
ans += dfs(length - ,bcd[s][i],ismax && i == limit ,false);
ans %= MOD;
}
}
if (!ismax && !zero) dp[length][s] = ans;
return ans;
} LL calcu(char * s)
{
int len = strlen(s + );
for (int i = ,j = len ; i <= len ; i++,j--)
digit[j] = s[i] - '';
// for (int j = 1 ; j <= len ; j++) printf("%d ",digit[j]); puts("");
return dfs(len,,true,true);
} char str[];
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int n;
src.init();
scanf("%d",&n);
for (int i = ; i < n ; i++)
{
scanf("%s",str);
src.insert(str,);
}
src.get_fail();
init();
memset(dp,-,sizeof(dp));
LL ans = ;
scanf("%s",str + );
int len = strlen(str + );
for (int i = len ; i >= ; i--)
{
if (str[i] > '')
{
str[i]--;
break;
}
else str[i] = '';
}
ans -= calcu(str);
ans %= MOD;
//cout << calcu(str) << endl;
scanf("%s",str + );
// cout << calcu(str) << endl;
ans += calcu(str);
ans %= MOD;
if (ans < ) ans += MOD;
printf("%lld\n",ans);
}
return ;
}

HDU 4758 Walk Through Squares

题意:给n*m的地图,在地图的点上走,(n+1)*(m+1)个点,两种操作:往下走D和往右走R。现在要从左上角走到右下角,给定两个操作串,问包含这两个串的走法总共有多少种。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MOD = 1e9 + ;
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
int dp[][][][];
int M,N;
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(char c)
{
if (c == 'R') return ;
else return ;
} void insert(char * s,int v)
{
int u = ,n = strlen(s);
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (ch[u][c] == )
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
// fail[0] = 0;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u != )
{
fail[u] = ;
q.push(u);
last[u] = ;
}
//else ch[0][c] = 0;
}
while (!q.empty())
{
int r = q.front();q.pop();
if(val[fail[r]]) val[r] |= val[fail[r]];
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
val[u] |= val[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
//cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
memset(val,,sizeof());
val[] = ;
} void slove()
{
memset(dp,,sizeof(dp));
dp[][][][] = ;
for (int i = ; i <= M ; i++)
for (int j = ; j <= N; j++)
for (int s = ; s < sz ; s++)
for (int k = ; k < ; k++)
{
if (dp[i][j][s][k] == ) continue;
int nxt = ch[s][];
if (i < M)
dp[i + ][j][nxt][k | val[nxt]] = (dp[i + ][j][nxt][k | val[nxt]]
+ dp[i][j][s][k]) % MOD;
nxt = ch[s][];
if (j < N)
dp[i][j + ][nxt][k | val[nxt]] = (dp[i][j + ][nxt][k | val[nxt]]
+ dp[i][j][s][k]) % MOD;
}
int ret = ;
for (int i = ; i < sz ; i++)
ret = (ret + dp[M][N][i][]) % MOD;
printf("%d\n",ret);
}
}src; int main()
{
//freopen("sample.txt","r",stdin);
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&M,&N);
src.init();
for (int i = ; i < ; i++)
{
char str[];
scanf("%s",str);
src.insert(str, << i);
}
src.get_fail();
src.slove();
// for (int i = 0 ; i < src.sz ; i++)
// printf("%d %d\n",src.ch[i][0],src.ch[i][1]);
}
return ;
}

HDU 4511 小明系列故事――女友的考验

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double INF = 1e20;
const int MAXNNODE = ;
const int SIGMA_SIZE = ;
double dp[][MAXNNODE];
int N,M;
struct node
{
double x,y;
}input[];
double dist(int i ,int j)
{
return sqrt((input[i].x - input[j].x) * (input[i].x - input[j].x) +
(input[i].y - input[j].y) * (input[i].y - input[j].y));
}
struct Ac_Automation
{
int ch[MAXNNODE][SIGMA_SIZE];
int val[MAXNNODE];
int fail[MAXNNODE],last[MAXNNODE];
int sz;
Ac_Automation() {sz = ;memset(ch[],,sizeof(ch[]));}
int idx(int c) {return c;} void insert(int * s,int v,int n)
{
int u = ;
for (int i = ; i < n ; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;//最后的叶子节点给与信息v
} //建立字典树 void get_fail()
{
queue<int>q;
fail[] = ;
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[][c];
if (u)
{
fail[u] = ;
q.push(u);
last[u] = ;
}
}
while (!q.empty())
{
int r = q.front();q.pop();
val[r] |= val[fail[r]];
for (int c = ; c < SIGMA_SIZE ; c++)
{
int u = ch[r][c];
if (u == )
{
ch[r][c] = ch[fail[r]][c];
continue;
}
q.push(u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
} void print(int j)
{
if (j)
{
// printf("%d\n",val[j]);
//cnt[val[j]]++;
print(last[j]);
}
} void Find(char * T)
{
int n = strlen(T);
int j = ;
for (int i = ; i < n ; i++)
{
int c = idx(T[i]);
// while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if (val[j]) print(j);
else if (last[j]) print(last[j]);//print是功能函数
}
} void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
} double slove()
{
for (int i = ; i < MAXNNODE ; i++)
for (int j = ; j < ; j++) dp[j][i] = INF;
dp[][ch[][]] = 0.0;
for (int i = ; i <= N; i++)
for (int j = ; j < sz ; j++)
{
if (dp[i][j] == INF) continue;
for (int k = i + ; k <= N; k++)
{
int nxt = ch[j][k];
if (val[nxt]) continue;
dp[k][nxt] = min(dp[k][nxt],dp[i][j] + dist(i,k));
}
}
double ret = INF;
for (int i = ; i < sz ; i++)
ret = min(ret,dp[N][i]);
return ret;
}
}src;
int main()
{
// freopen("sample.txt","r",stdin);
while (scanf("%d%d",&N,&M) != EOF)
{
if (N == && M == ) break;
src.init();
for (int i = ; i <= N; i++) scanf("%lf%lf",&input[i].x,&input[i].y);
for (int i = ; i < M; i++)
{
int k;
scanf("%d",&k);
int tmp[];
for (int i = ; i < k ; i++) scanf("%d",&tmp[i]);
src.insert(tmp,,k);
}
src.get_fail();
double ret = src.slove();
if (ret == INF) puts("Can not be reached!");
else printf("%.2lf\n",ret);
}
return ;
}

Kuangbin带你飞 AC自动机的更多相关文章

  1. 「kuangbin带你飞」专题十七 AC自动机

    layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...

  2. KUANGBIN带你飞

    KUANGBIN带你飞 全专题整理 https://www.cnblogs.com/slzk/articles/7402292.html 专题一 简单搜索 POJ 1321 棋盘问题    //201 ...

  3. [kuangbin带你飞]专题1-23题目清单总结

    [kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...

  4. 「kuangbin带你飞」专题十四 数论基础

    layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...

  5. 「kuangbin带你飞」专题十二 基础DP

    layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathj ...

  6. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  7. Tarjan 联通图 Kuangbin 带你飞 联通图题目及部分联通图题目

    Tarjan算法就不说了 想学看这 https://www.byvoid.com/blog/scc-tarjan/ https://www.byvoid.com/blog/biconnect/ 下面是 ...

  8. 「kuangbin带你飞」专题二十 斜率DP

    layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...

  9. 「kuangbin带你飞」专题二十二 区间DP

    layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - ku ...

随机推荐

  1. 13-Mysql数据库----权限设置

    权限管理 我们知道我们的最高权限管理者是root用户,它拥有着最高的权限操作.包括select.update.delete.update.grant等操作.那么一般情况在公司之后DBA工程师会创建一个 ...

  2. Gym101981I Magic Potion(最大流)

    Problem I. Magic Potion There are n heroes and m monsters living in an island. The monsters became v ...

  3. this.getClass().getResource()示例详解

    public class ResourceTest extends TimerTask{ @Override    public void run() {        System.out.prin ...

  4. PokeCats开发者日志(一)

      现在是PokeCats游戏开发的第三天的上午,突然心血来潮想记录一下这个开发过程,于是写起了开发者日志. day1   作为一只ACM退役喵,寒假回家,闲着没事,天天在召唤师峡谷里闲逛也挺没意思的 ...

  5. 手动修改PHP页面返回状态码

    <?php //比如当前页面要返回404状态码 header("HTTP/1.1 404 Not Found"); header("Status: 404 Not ...

  6. vue-cli项目里npm安装font-awesome

    第一步:进入到项目目录里,运行 cnpm i font-awesome -s 第二步:在main.js里面 import 'font-awesome/css/font-awesome.min.css'

  7. Hibernate对象状态

    对象状态 瞬时(transient) 自己new出来的对象,数据库没有记录与之对应,与session也没有关联 持久(persistent) 数据库中有记录与之对应,当前与session有关联,相关的 ...

  8. P4018 Roy&October之取石子

    题目背景 Roy和October两人在玩一个取石子的游戏. 题目描述 游戏规则是这样的:共有n个石子,两人每次都只能取 p^kpk 个(p为质数,k为自然数,且 p^kpk 小于等于当前剩余石子数), ...

  9. mplab c30 注册方法

    http://blog.csdn.net/q553716434/article/details/7459036 关键文件是: C:\Program Files\Microchip\MPLAB C30\ ...

  10. 安徽师大附中%你赛day5 T3 树上行走 解题报告

    树上行走 题目背景 \(\mathrm{Smart}\) 的脑洞非常大, 经常幻想出一些奇怪的东西. 题目描述 某一天,\(\mathrm{Smart}\) 幻想出了一棵没有边际的二叉树,脑补着在那棵 ...