DP Finite Automata with Compression: Password Counting
You now need to design a password S,S Need to meet:
S The length is N; S Only contain lowercase English letters; S Does not contain substring T; E.g: abc and abcde are abcde’s substring while abde is not a substring of abcde.
How many different passwords meet the requirements?
Since the answer will be very large, please output the answer modulus 109 + 7 The remainder.
Input format
Enter the integer N in the first line to indicate the length of the password.
Enter the string T on the second line. T contains only lowercase letters.
Output format
Output a positive integer , which means the total password number modulus109+ 7 After the result.
data range
Sample Input:
4
cbc
Sample Output:
456924
Solution
Use T to generate a KMP state transition table. Looping from 0 to N and test every possible charater (a-z), the KMP state transition from j to newJ based on charater in position i+1. Add the numbers to that state.
dp[i][j]: the number of passwords so far from 0 to i-th Position
- i is the i-th position of the password(< N)
- j is the j-th state of KMP state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=55,mod=1e9+7;
int dp[N][N],kmp_table[N][26];
void buildKMPTable(string s) {
int m = s.length();
int x = 0;
kmp_table[0][0] = 1;
for (int i = 1; i < m; ++i) {
for (char ch = 'a'; ch <= 'z'; ++ch) {
if (ch == s[i]) {
kmp_table[i][ch - 'a'] = i + 1;
} else {
kmp_table[i][ch - 'a'] = kmp_table[x][ch - 'a'];
}
}
x = kmp_table[x][s[i] - 'a'];
}
}
int main()
{
int n;
cin>>n;
string T;
cin>>T;
int m= T.length();
//create KMP state transition table based on T
buildKMPTable(T);
//inialize the empty password as count 1
dp[0][0]=1;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
//iterate through all possible value of charater in position i + 1
for(char k='a';k<='z';k++)
{
int u=kmp_table[j][k - 'a'];
if(u<m)
dp[i+1][u]=(dp[i+1][u]+dp[i][j])%mod;
}
int res=0;
for(int i=0;i<m;i++)
res=(res + dp[n][i])%mod;
printf("%d",res);
return 0;
}