[Question solution] CF808G Anthem of Berland

Title

Portal luogu

answer

The ingenious combination of dp and kmp.

Let the length of the text string s be nnn , the length of the pattern string t ismmm . The title tells you nakedly thatnm ≤ 1 0 7 nm\leq 10^7nm107. This clarifies that the complexity should be inO (nm) O(nm)O ( n m ) this level, thisnnThe complexity of n is definitely to scan s, as formmm , it can be guessed that it is a violent match for each position of s.

We can consider dp to solve this problem. Let fi f_ifiIndicates that t is before s iiThe largest number of occurrences of i positions. Then if a position wants to be transferred from the previous position, it must be satisfied that t can match with s at this position, and this part can beO (m) O (m)O ( m ) Violent judgment.

How to transfer it? First of all, it is obvious that you can directly start from fi − m f_{im}fimTransferred over, it means i − m + 1 ∼ i i-m+1\sim iim+1Put a complete t in this section i .

But this is not enough, because it is possible to place several t consecutively and overlappingly before this position, which means that the newly placed t is not complete, but is formed by overlapping the suffix of the previous t. Then it needs to satisfy that a suffix of t is equal to a prefix.

This brings us to the next array in the kmp algorithm. We can ensure that the prefix is ​​equal to the suffix by jumping next from m.

But there is another problem, suppose we now have a length of kkThe prefixes and suffixes of k are equal, but we cannot directlycalculatefromfi − (m − k) f_{i-(mk)}fi(mk)Transfer because ffThe definition of f does not guaranteefi − (m − k) f_(i-(mk))fi(mk)There must be a t in this position.

So we define another gi g_igi, Which means the front ii of si positions, forcing the maximum number of occurrences of t to be placed last. Then we can passgg in theabove situationThe transfer between g is realized. That is,gi = max ⁡ {gi − (m − k) + 1, gi} g_i=\max\{g_{i-(mk)}+1,g_i\}gi=max{ gi(mk)+1,gi} , Just keep skipping next update.

Transfer ggAfter g , we then setfi = max ⁡ {fi − 1, gi} f_i=\max\{f_{i-1}, g_i\}fi=max{ fi1,gi} , That is, consider the two cases of putting and not putting t.

Code

#include <bits/stdc++.h>
#define MAX 100005
using namespace std;

char s[MAX], t[MAX];
int n, m;
int Next[MAX], f[MAX], g[MAX];

bool chk(int p){
    
    
    for(int j = 1; j <= m; j++){
    
    
        if(s[p-j+1] != t[m-j+1] && s[p-j+1] != '?') return false;
    }
    return true;
}

int main()
{
    
    
    scanf("%s%s", s+1, t+1);
    n = strlen(s+1), m = strlen(t+1);
    for(int i = 2, j = 0; i <= m; i++){
    
    
        while(j && t[j+1] != t[i]) j = Next[j];
        if(t[j+1] == t[i]) j++;
        Next[i] = j;
    }

    for(int i = 1; i <= n; i++){
    
    
        f[i] = f[i-1];
        if(chk(i)){
    
    
            g[i] = f[i-m]+1;
            for(int j = Next[m]; j; j = Next[j]){
    
    
                g[i] = max(g[i], g[i-(m-j)]+1);
            }
            f[i] = max(f[i], g[i]);
        }
    }
    cout << f[n] << endl;

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_30115697/article/details/104867085