题目大意
给定一个长度
n
和一个危险串
求有多少个长度为
n
的只包含小写字母的字符串不包含危险串。
Data Constraint
题解
设
f[i][j]
表示,当前处理完前
i
位,匹配到
考虑枚举
Next
可以用KMP预处理。
时间复杂度: O(nm)
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std ;
#define N 10000 + 10
#define M 100 + 10
typedef long long ll ;
const int MO = 1e9 + 7 ;
char str[M] ;
int P[M] , Next[M][26] ;
ll f[N][M] ;
int n , m , ans ;
int Power( int x , int k ) {
int s = 1 ;
while ( k ) {
if ( k & 1 ) s = (ll)s * x % MO ;
x = (ll)x * x % MO ;
k /= 2 ;
}
return s ;
}
int main() {
freopen( "helloworld.in" , "r" , stdin ) ;
freopen( "helloworld.out" , "w" , stdout ) ;
while ( scanf( "%d" , &n ) != EOF ) {
scanf( "%s" , str + 1 ) ;
bool flag = 1 ;
int len = strlen( str + 1 ) ;
memset( P , 0 , sizeof(P) ) ;
memset( Next , 0 , sizeof(Next) ) ;
for (int i = 1 ; i <= len ; i ++ ) {
if ( str[i] < 'a' || str[i] > 'z' ) { flag = 0 ; break ; }
int j = P[i-1] ;
while ( j && str[j+1] != str[i] ) j = P[j] ;
if ( i > 1 && str[j+1] == str[i] ) P[i] = j + 1 ;
for (int c = 0 ; c < 26 ; c ++ ) {
if ( c + 'a' == str[i+1] ) { Next[i][c] = i + 1 ; continue ; }
int k = P[i] ;
while ( k && str[k+1] != c + 'a' ) k = P[k] ;
if ( str[k+1] == c + 'a' ) Next[i][c] = k + 1 ;
}
}
if ( !flag ) { printf( "%d\n" , Power( 26 , n ) ) ; continue ; }
memset( f , 0 , sizeof(f) ) ;
f[0][0] = 1 ;
for (int i = 0 ; i < n ; i ++ ) {
for (int j = 0 ; j < len ; j ++ ) {
for (int c = 0 ; c < 26 ; c ++ ) {
if ( str[j+1] != c + 'a' ) f[i+1][Next[j][c]] = (f[i+1][Next[j][c]] + f[i][j]) % MO ;
else f[i+1][j+1] = (f[i+1][j+1] + f[i][j]) % MO ;
}
}
}
ans = 0 ;
for (int i = 0 ; i < len ; i ++ ) ans = (ans + f[n][i]) % MO ;
printf( "%d\n" , ans ) ;
}
return 0 ;
}
以上.