Progressive hard octave rock tunes (so-called “phorts”) are written using a specifific music notation. This flflavor of rock is built on just 13 difffferent note pitches, other pitches (in other octaves)are considered to be an outdated musical ballast. Each note can be either a long one or a shortone. Consequently, there are exactly 26 difffferent notes in the rock.
You are going to compose a phort tune on the occasion of your friend’s birthday and perform itwith your band on the main town square. While composing the phort, you need to avoid certainmusical phrases, which are heavily copyrighted as a result of long research sponsored by bigrecord companies. It has been established that these phrases are very catchy, easy to remember,and could be exploited to bind the listeners subconsciously to a particular music company whichwould utilize these phrases in their production.
The tune is a sequence of notes. A musical phrase is also a sequence of notes and it is consideredto be contained in a tune if its notes form a contiguous subsequence of the tune, which meansthe same notes appear in the tune right after each other in the same order.
Fortunately, only a few forbidden phrases have been patented so far. Thus, you have a relativefreedom in composing your own tunes. In particular, you are interested in the number ofacceptable tunes of some length. An acceptable tune is any tune which does not contain aforbidden phrase. The length of the tune is equal to the number of notes it contains.
Input Specifification
The first line contains two integers N, Q (1 ≤ N ≤ 10^9, 1 ≤ Q ≤ 100)N,Q(1≤N≤10
9
,1≤Q≤100). NN is the length of the tune, QQ is the number of forbidden musical phrases. Each of the Q following lines describes one forbidden phrase. A description of a forbidden phrase starts with a positive integer LL, indicating its length, followed by a string of LL lowercase English letters. Each letter represents one rock note, different letters represent different notes.
The sum of lengths of all forbidden phrases does not exceed 100
Output Specification
Output the number of different acceptable tunes of length NN. Print the result modulo 1 000 000 007.
样例输入1复制
2 3
1 a
1 b
1 c
样例输出1复制
529
样例输入2复制
3 3
2 aa
1 a
1 a
样例输出2复制
15625
样例输入3复制
3 1
2 ab
样例输出3复制
17524
题意:
长度为n的序列,每个位置可以填任意一个小写字母。但要求不能出现m种子串。求方案数。
思路:
你以为你换了个马甲我就不认得了吗(认真脸) ?
这是道原题 POJ 2778
https://blog.csdn.net/tomjobs/article/details/106889258
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 1e6 + 7;
const int mod = 1e9 + 7;
typedef long long ll;
struct Trie {
int son[30],val,fail;
}t[maxn];
struct Matrix {
ll m[101][101];
}M;
ll m;
int n,cnt,id[505];
char s[maxn];
void init() {
for(int i = 0;i <= cnt;i++) {
memset(t[i].son,0,sizeof(t[i].son));
t[i].val = t[i].fail = 0;
}
cnt = 0;
for(int i = 0;i < 26;i++) {
id[i + 'a'] = i;
}
}
void insert(char *s) {
int u = 0,len = strlen(s);
for(int i = 0;i < len;i++) {
int v = id[s[i]];
if(!t[u].son[v]) t[u].son[v] = ++cnt;
u = t[u].son[v];
}
t[u].val++;
}
void getFail() {
queue<int>q;
q.push(0);t[0].fail = 0;
while(!q.empty()) {
int u = q.front();q.pop();
if(t[t[u].fail].val) {
t[u].val = 1;
}
for(int i = 0;i < 26;i++) {
int v = t[u].son[i];
int Fail = t[u].fail;
if(!v) {
t[u].son[i] = t[Fail].son[i];continue; //直接让不存在的儿子指向失配位置
}
if(Fail == 0 && t[Fail].son[i] == v) t[v].fail = 0;
else t[v].fail = t[Fail].son[i];
q.push(v);
}
}
}
void build() {
for(int i = 0;i <= cnt;i++) {
for(int j = 0;j < 26;j++) {
if(!t[i].val && !t[t[i].son[j]].val) {
M.m[i][t[i].son[j]]++;
}
}
}
}
Matrix mul(Matrix A,Matrix B) {
Matrix C;
memset(C.m,0,sizeof(C.m));
for(int i = 0;i <= cnt;i++) {
for(int j = 0;j <= cnt;j++) {
C.m[i][j] = 0;
for(int k = 0;k <= cnt;k++) {
C.m[i][j] = (C.m[i][j] + A.m[i][k] * B.m[k][j]) % mod;
}
}
}
return C;
}
Matrix Pow(Matrix A,ll n) {
Matrix res;
memset(res.m,0,sizeof(res.m));
for(int i = 0;i <= cnt;i++) res.m[i][i] = 1;
while(n) {
if(n & 1) {
res = mul(res,A);
}
A = mul(A,A);
n >>= 1;
}
return res;
}
int main() {
init();
scanf("%lld %d",&m,&n);
for(int i = 1;i <= n;i++) {
int x;scanf("%d",&x);
scanf("%s",s);
insert(s);
}
getFail();
build();
Matrix res = Pow(M,m);
ll ans = 0;
for(int i = 0;i <= cnt;i++) {
ans = (ans + res.m[0][i]) % mod;
}
printf("%lld\n",ans);
return 0;
}

797

被折叠的 条评论
为什么被折叠?



