Poj 2778
#include
<
stdio.h
>
#include < string .h >
#include < stdlib.h >
#include < algorithm >
#define N 105
using namespace std;
struct tree{
tree * next[ 4 ], * fail;
int flag, num;
} * root, * p;
tree arr[ 1000 ];
int indexx;
int map( char ch){
if (ch == ' A ' ) return 0 ;
if (ch == ' C ' ) return 1 ;
if (ch == ' T ' ) return 2 ;
if (ch == ' G ' ) return 3 ;
}
void newn(){
arr[indexx].flag = 0 ;
arr[indexx].num = indexx;
for ( int i = 0 ; i < 4 ; i ++ ){
arr[indexx].next[i] = 0 ;
}
}
void init(){
indexx = 0 ;
newn();
root = & arr[indexx ++ ];
}
void insert( char ch[], int w){
int t, i = 0 ;
p = root;
while (ch[i]){
t = map(ch[i]);
if (p -> next[t] == 0 ){
newn();
p -> next[t] = & arr[indexx ++ ];
}
p = p -> next[t];
i ++ ;
}
p -> flag = w;
}
tree * que[ 10000 ];
bool search(tree * q)
{
while (q != root)
{
if (q -> flag) return true ;
q = q -> fail;
}
return false ;
}
void get_fail(){
p = root;
p -> fail = root;
int open = 0 , close = - 1 , i;
que[ 0 ] = p;
while (close < open){
p = que[ ++ close];
tree * q = p;
int pass = 0 ;
if (q -> flag == 0 ) pass = search(q);
if (pass) p -> flag = 1 ;
for (i = 0 ; i < 4 ; i ++ )
{
if (p -> next[i] == 0 ){
if (p == root) p -> next[i] = root;
else p -> next[i] = p -> fail -> next[i];
}
else {
if (p == root) p -> next[i] -> fail = root;
else p -> next[i] -> fail = p -> fail -> next[i];
que[ ++ open] = p -> next[i];
}
}
}
}
long long n;
int m;
long long f[N][N];
#define M 100000
void mod_multi( long long a[N][N], long long b[N][N], int r){ // A=A*B%M A为r*r矩阵
int i, j, k;
long long c[N][N] = {};
for (k = 0 ; k < r; k ++ )
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ ){
c[i][j] += a[i][k] * b[k][j];
c[i][j] %= M;
}
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ )
a[i][j] = c[i][j];
}
void mod_exp( long long a[N][N], long long n, int r){ // A=A^n%m A为r*r矩阵
int i, j, k;
long long ans[N][N] = {};
for (i = 0 ; i < r; i ++ )ans[i][i] = 1 ; // 单位阵
for (; n; n >>= 1 ){
if (n & 1 )
mod_multi(ans, a, r);
mod_multi(a, a, r);
}
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ )
a[i][j] = ans[i][j];
}
int main(){
while (scanf( " %d %lld " , & m, & n) != EOF){
init();
char str[ 12 ];
for ( int i = 0 ; i < m; i ++ ){
scanf( " %s " , str);
insert(str, 1 );
}
get_fail();
memset(f, 0 , sizeof (f));
for ( int i = 0 ; i < indexx; i ++ ){
for ( int j = 0 ; j < 4 ; j ++ ){
if (arr[i].next[j] -> flag == 0 && arr[i].flag == 0 )
f[i][arr[i].next[j] -> num] ++ ;
}
}
mod_exp(f, n, indexx);
long long ans = 0 ;
for ( int i = 0 ; i < indexx; i ++ ){
ans += f[ 0 ][i];
ans %= M;
}
printf( " %lld\n " , ans);
}
}
#include < string .h >
#include < stdlib.h >
#include < algorithm >
#define N 105
using namespace std;
struct tree{
tree * next[ 4 ], * fail;
int flag, num;
} * root, * p;
tree arr[ 1000 ];
int indexx;
int map( char ch){
if (ch == ' A ' ) return 0 ;
if (ch == ' C ' ) return 1 ;
if (ch == ' T ' ) return 2 ;
if (ch == ' G ' ) return 3 ;
}
void newn(){
arr[indexx].flag = 0 ;
arr[indexx].num = indexx;
for ( int i = 0 ; i < 4 ; i ++ ){
arr[indexx].next[i] = 0 ;
}
}
void init(){
indexx = 0 ;
newn();
root = & arr[indexx ++ ];
}
void insert( char ch[], int w){
int t, i = 0 ;
p = root;
while (ch[i]){
t = map(ch[i]);
if (p -> next[t] == 0 ){
newn();
p -> next[t] = & arr[indexx ++ ];
}
p = p -> next[t];
i ++ ;
}
p -> flag = w;
}
tree * que[ 10000 ];
bool search(tree * q)
{
while (q != root)
{
if (q -> flag) return true ;
q = q -> fail;
}
return false ;
}
void get_fail(){
p = root;
p -> fail = root;
int open = 0 , close = - 1 , i;
que[ 0 ] = p;
while (close < open){
p = que[ ++ close];
tree * q = p;
int pass = 0 ;
if (q -> flag == 0 ) pass = search(q);
if (pass) p -> flag = 1 ;
for (i = 0 ; i < 4 ; i ++ )
{
if (p -> next[i] == 0 ){
if (p == root) p -> next[i] = root;
else p -> next[i] = p -> fail -> next[i];
}
else {
if (p == root) p -> next[i] -> fail = root;
else p -> next[i] -> fail = p -> fail -> next[i];
que[ ++ open] = p -> next[i];
}
}
}
}
long long n;
int m;
long long f[N][N];
#define M 100000
void mod_multi( long long a[N][N], long long b[N][N], int r){ // A=A*B%M A为r*r矩阵
int i, j, k;
long long c[N][N] = {};
for (k = 0 ; k < r; k ++ )
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ ){
c[i][j] += a[i][k] * b[k][j];
c[i][j] %= M;
}
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ )
a[i][j] = c[i][j];
}
void mod_exp( long long a[N][N], long long n, int r){ // A=A^n%m A为r*r矩阵
int i, j, k;
long long ans[N][N] = {};
for (i = 0 ; i < r; i ++ )ans[i][i] = 1 ; // 单位阵
for (; n; n >>= 1 ){
if (n & 1 )
mod_multi(ans, a, r);
mod_multi(a, a, r);
}
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ )
a[i][j] = ans[i][j];
}
int main(){
while (scanf( " %d %lld " , & m, & n) != EOF){
init();
char str[ 12 ];
for ( int i = 0 ; i < m; i ++ ){
scanf( " %s " , str);
insert(str, 1 );
}
get_fail();
memset(f, 0 , sizeof (f));
for ( int i = 0 ; i < indexx; i ++ ){
for ( int j = 0 ; j < 4 ; j ++ ){
if (arr[i].next[j] -> flag == 0 && arr[i].flag == 0 )
f[i][arr[i].next[j] -> num] ++ ;
}
}
mod_exp(f, n, indexx);
long long ans = 0 ;
for ( int i = 0 ; i < indexx; i ++ ){
ans += f[ 0 ][i];
ans %= M;
}
printf( " %lld\n " , ans);
}
}
另一个版本的比之高效很多
#include
<
stdio.h
>
#include < string .h >
#define R 5
#define N 105
#define M 100000
typedef long long LL;
int tree[N][R], flag[N], fail[N], state;
int cha[ 128 ] = {};
void init(){
cha[ ' A ' ] = 1 ; cha[ ' T ' ] = 2 ;
cha[ ' G ' ] = 3 ; cha[ ' C ' ] = 4 ;
memset(tree, - 1 , sizeof (tree));
memset(flag, 0 , sizeof (flag));
memset(fail, - 1 , sizeof (fail));
flag[ 0 ] = 0 ;
state = 1 ;
}
void insert( char ch[]) {
int p = 0 , i = 0 , t;
while (ch[i]) {
t = cha[ch[i]];
if (tree[p][t] < 0 ) {
flag[state] = 0 ;
tree[p][t] = state ++ ;
}
p = tree[p][t];
i ++ ;
}
flag[p] = 1 ;
}
int que[N];
void get_fail() {
int close = - 1 , open = 0 ;
que[ 0 ] = 0 ;
fail[ 0 ] = 0 ;
while (close < open) {
int p = que[ ++ close];
for ( int i = 0 ; i < R; i ++ ) {
if (tree[p][i] == - 1 ){
if (p == 0 ) tree[p][i] = 0 ;
else tree[p][i] = tree[fail[p]][i];
} else {
if (p == 0 ) fail[tree[p][i]] = 0 ;
else fail[tree[p][i]] = tree[fail[p]][i];
que[ ++ open] = tree[p][i];
}
}
}
}
int n, L;
LL f[N][N], sum = 0 ;
void mod_multi(LL a[N][N], LL b[N][N], int r){
int i, j, k;
LL c[N][N] = {};
for (k = 0 ; k < r; k ++ )
for (i = 0 ; i < r; i ++ )
if (a[i][k])
for (j = 0 ; j < r; j ++ ){
c[i][j] += a[i][k] * b[k][j];
c[i][j] %= M;
}
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ )
a[i][j] = c[i][j];
}
void mod_exp(LL a[N][N], LL n, int r){
int i, j, k;
LL ans[N][N] = {};
for (i = 0 ; i < r; i ++ )ans[i][i] = 1 ;
for (; n; n >>= 1 ){
if (n & 1 )
mod_multi(ans, a, r);
mod_multi(a, a, r);
}
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ )
a[i][j] = ans[i][j];
}
LL fast(LL sum, int L) {
LL temp = 1ll;
for (;L;L >>= 1 ) {
if (L & 1 ) {
temp *= sum;
temp %= M;
}
sum *= sum;
sum %= M;
}
return temp;
}
bool search( int q) {
while (q != 0 ) {
if (flag[q]) return true ;
q = fail[q];
}
return false ;
}
int main() {
while (scanf( " %d %d " , & n , & L) != EOF) {
char str[ 11 ];
init();
for ( int i = 0 ; i < n; i ++ ) {
scanf( " %s " , str);
insert(str);
}
get_fail();
int map[N], cnt = 0 , t;
memset(map, - 1 , sizeof (map));
memset(f, 0 , sizeof (f));
for ( int i = 0 ; i < state; i ++ ) {
if (flag[i] == 0 ) flag[i] = search(i);
}
for ( int i = 0 ; i < state; i ++ ) {
if (flag[i] == 0 )
for ( int j = 1 ; j < R; j ++ ) {
if (flag[tree[i][j]] == 0 ) {
t = tree[i][j];
if (map[i] == - 1 ) map[i] = cnt ++ ;
if (map[t] == - 1 ) map[t] = cnt ++ ;
f[map[i]][map[t]] ++ ;
}
}
}
mod_exp(f, L, cnt);
LL ans = 0 ;
for ( int i = 0 ; i < cnt; i ++ ) {
ans += f[ 0 ][i];
ans %= M;
}
printf( " %lld\n " , ans);
}
}
#include < string .h >
#define R 5
#define N 105
#define M 100000
typedef long long LL;
int tree[N][R], flag[N], fail[N], state;
int cha[ 128 ] = {};
void init(){
cha[ ' A ' ] = 1 ; cha[ ' T ' ] = 2 ;
cha[ ' G ' ] = 3 ; cha[ ' C ' ] = 4 ;
memset(tree, - 1 , sizeof (tree));
memset(flag, 0 , sizeof (flag));
memset(fail, - 1 , sizeof (fail));
flag[ 0 ] = 0 ;
state = 1 ;
}
void insert( char ch[]) {
int p = 0 , i = 0 , t;
while (ch[i]) {
t = cha[ch[i]];
if (tree[p][t] < 0 ) {
flag[state] = 0 ;
tree[p][t] = state ++ ;
}
p = tree[p][t];
i ++ ;
}
flag[p] = 1 ;
}
int que[N];
void get_fail() {
int close = - 1 , open = 0 ;
que[ 0 ] = 0 ;
fail[ 0 ] = 0 ;
while (close < open) {
int p = que[ ++ close];
for ( int i = 0 ; i < R; i ++ ) {
if (tree[p][i] == - 1 ){
if (p == 0 ) tree[p][i] = 0 ;
else tree[p][i] = tree[fail[p]][i];
} else {
if (p == 0 ) fail[tree[p][i]] = 0 ;
else fail[tree[p][i]] = tree[fail[p]][i];
que[ ++ open] = tree[p][i];
}
}
}
}
int n, L;
LL f[N][N], sum = 0 ;
void mod_multi(LL a[N][N], LL b[N][N], int r){
int i, j, k;
LL c[N][N] = {};
for (k = 0 ; k < r; k ++ )
for (i = 0 ; i < r; i ++ )
if (a[i][k])
for (j = 0 ; j < r; j ++ ){
c[i][j] += a[i][k] * b[k][j];
c[i][j] %= M;
}
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ )
a[i][j] = c[i][j];
}
void mod_exp(LL a[N][N], LL n, int r){
int i, j, k;
LL ans[N][N] = {};
for (i = 0 ; i < r; i ++ )ans[i][i] = 1 ;
for (; n; n >>= 1 ){
if (n & 1 )
mod_multi(ans, a, r);
mod_multi(a, a, r);
}
for (i = 0 ; i < r; i ++ )
for (j = 0 ; j < r; j ++ )
a[i][j] = ans[i][j];
}
LL fast(LL sum, int L) {
LL temp = 1ll;
for (;L;L >>= 1 ) {
if (L & 1 ) {
temp *= sum;
temp %= M;
}
sum *= sum;
sum %= M;
}
return temp;
}
bool search( int q) {
while (q != 0 ) {
if (flag[q]) return true ;
q = fail[q];
}
return false ;
}
int main() {
while (scanf( " %d %d " , & n , & L) != EOF) {
char str[ 11 ];
init();
for ( int i = 0 ; i < n; i ++ ) {
scanf( " %s " , str);
insert(str);
}
get_fail();
int map[N], cnt = 0 , t;
memset(map, - 1 , sizeof (map));
memset(f, 0 , sizeof (f));
for ( int i = 0 ; i < state; i ++ ) {
if (flag[i] == 0 ) flag[i] = search(i);
}
for ( int i = 0 ; i < state; i ++ ) {
if (flag[i] == 0 )
for ( int j = 1 ; j < R; j ++ ) {
if (flag[tree[i][j]] == 0 ) {
t = tree[i][j];
if (map[i] == - 1 ) map[i] = cnt ++ ;
if (map[t] == - 1 ) map[t] = cnt ++ ;
f[map[i]][map[t]] ++ ;
}
}
}
mod_exp(f, L, cnt);
LL ans = 0 ;
for ( int i = 0 ; i < cnt; i ++ ) {
ans += f[ 0 ][i];
ans %= M;
}
printf( " %lld\n " , ans);
}
}