Combination of KMP with AC automata and DP

Design password
Now you need to design a password S , S S,S S. S needs to meet:

S The length of the is N;
S Contains only lowercase English letters;
S Contains no substrings T;

For example: a b c abc abc and a b c d e abcde abcde yes a b c d e abcde Substring of abcde, a b d abd abd is not a b c d e abcde Substring of abcde.

How many different passwords meet the requirements?

(as the answer will be very large, please output the answer module 1 e 9 + 7 1e9+7 The remainder of 1e9+7.)

Input format
Enter an integer on the first line N N N. Indicates the length of the password.

The second line is the input string T , T T,T T. T contains only lowercase letters.

Output format
Output a positive integer representing the digital analog of the total scheme 1 e 9 + 7 1e9+7 Results after 1e9+7.

Data range
1 ≤ N ≤ 50 1≤N≤50 1≤N≤50,
1 ≤ ∣ T ∣ ≤ N 1≤|T|≤N 1≤∣T∣≤N, ∣ T ∣ |T| ∣ T ∣ yes T T Length of T.

This topic is the combination of DP and KMP. The specific state design is:
f [ i ] [ j ] : structure make Yes front i individual word mother , And When front word mother yes strand T of shape state yes j , ( this individual shape state finger of yes T of K M P of n e x t number group ) f[i][j]: the first I letters are constructed, and the status of the current letter pair string t is j, \ \ (this status refers to the next array of KMP of T) f[i][j]: the first I letters are constructed, and the state of the current letter pair string t is j, (this state refers to the next array of KMP of T)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int N = 55, mod = 1e9 + 7;

int n, m;
int f[N][N];
//f[i][j] represents all schemes with the first I letters and the state of string T is j
char T[N];
int ne[N];

int main()
{
	cin >> n >> T + 1;
	m = strlen(T + 1);
	
	//Find the next array of T 
	for(int i = 2, j = 0; i <= m; i++)
	{
		while(j && T[i] != T[j + 1])	j = ne[j];
		if(T[i] == T[j + 1])	j++;
		ne[i] = j;
	}
	
	f[0][0] = 1; //When the length is 0, the status is 0. There is only one scheme
	for(int i = 0; i <= n; i++) //Enumeration length 
		for(int j = 0; j <= m; j++)//Enumeration status 
			for(char k = 'a'; k <= 'z'; k++) //Enumerate the next letter 
			{
				int u = j;
				while(u && k != T[u + 1])	u = ne[u]; 
				//Find the state after transfer in the next array
				if(k == T[u + 1])	u++;
				if(u < m)	f[i + 1][u] = (f[i + 1][u] + f[i][j]) % mod;
				//If the status is legal, dp will be transferred. Legal means that the number of currently matched letters u is less than m
			}
			
	int res = 0;
	for(int i = 0; i < m; i++)	res = (res + f[n][i]) % mod;
	
	cout << res << endl;
	return 0;
}


Text generator

Title Description
JSOI gave team member ZYX a task to compile a computer software called "text generator": the users of the software are some young people, and they are now using version v6 of GW text generator.

The software can generate some articles randomly - always a fixed length and completely random article. That is, each character in the generated article is completely random. If an article contains at least one word that users know, then we say the article is readable (we call it an article) s s s contains words t t t. If and only if the word t t t is an article s s s). However, even according to such standards, the articles generated by the v6 version of GW text generator currently used by users are almost completely unreadable. ZYX needs to indicate the number of readable texts in all texts generated by GW text generator v6 in order to successfully obtain v7 update. Can you help him?

The answer is right 1 0 4 + 7 10^4 + 7 104 + 7 take mold.

Input format
The first line has two integers, representing the total number of words understood by the user n n n and generated article length m m m.
next n n n lines, one string per line s i s_i si, represents a word understood by the user.

Output format
Output an integer on a line to represent the answer pair 1 0 4 + 7 10^4 + 7 Results of 104 + 7 mold taking.

The last question is that the construction length is n n The number of strings that are n and do not contain a given substring.
The problem is that the construction length is n n The number of strings that are n and do not contain multiple given substrings

This question is the AC automata version of the previous question, and the state design is also similar to the previous question:
f [ i ] [ j ] : long degree yes i , stay a c since move machine upper of shape state yes j of place yes no package contain to set single Words of word symbol strand of individual number f[i][j]: the number of strings with length I and state j on ac automata that do not contain a given word f[i][j]: the number of strings with length I and state j on ac automata that do not contain a given word

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f

using namespace std;

typedef long long LL;

const int N = 110, M = 6010, Mod = 10007;

int n, m, f[N][M]; //f[i][j]: the number of strings with length I and state j on ac automata that do not contain a given word
int idx, tr[M][26], ne[M];
bool have[M];
char str[N];

void insert()
{
    int p = 0;
    for(int i = 0; str[i]; i ++)
    {
        int t = str[i] - 'A';
        if(!tr[p][t])   tr[p][t] = ++ idx;
        p = tr[p][t];
    }
    have[p] = true;
}

int q[M];
void build()
{
    int hh = 0, tt = -1;
    for(int i = 0; i < 26; i ++)
        if(tr[0][i])    q[++ tt] = tr[0][i];
    
    while(hh <= tt)
    {
        int u = q[hh ++];
        for(int i = 0; i < 26; i ++)
        {
            int &p = tr[u][i];
            if(!p)  p = tr[ne[u]][i];
            else
            {
                ne[p] = tr[ne[u]][i];
                q[++ tt] = p;
                have[p] |= have[ne[p]];
            }
        }
    }
}

int main()
{
#ifdef LOCAL
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif

    cin >> n >> m;
    for(int i = 0; i < n; i ++)
    {
        cin >> str;
        insert();
    }

    build();

    f[0][0] = 1;
    for(int i = 0; i < m; i ++) //Enumeration length
        for(int j = 0; j <= idx; j ++) //Enumeration status
            for(int k = 0; k < 26; k ++) //What's next
            {
                int p = tr[j][k];
                if(!have[p])    f[i + 1][p] = (f[i + 1][p] + f[i][j]) % Mod; 
                //If the state is legal, dp will be transferred. Legal means that there is no string ending at p
            }
    int ans = 1;
    for(int i = 0; i < m; i ++) ans = (ans * 26) % Mod;
    for(int i = 0; i <= idx; i ++)  ans = (ans - f[m][i] + Mod) % Mod;

    cout << ans << endl;

    return 0;
}

Keywords: C Algorithm Dynamic Programming

Added by cjacks on Wed, 22 Sep 2021 01:23:51 +0300