Title
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^7nm≤107. 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}fi−mTransferred over, it means i − m + 1 ∼ i i-m+1\sim ii−m+1∼Put 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−(m−k)Transfer because ffThe definition of f does not guaranteefi − (m − k) f_(i-(mk))fi−(m−k)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−(m−k)+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{ fi−1,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;
}