对每个字符,做一遍匹配的NTT, 即设每个位置能匹配的值为f_i, 那么f_i = s_i + j == t_j(0 < j < t.size() ),然后每个字符都匹配一下,加到一起,暴力枚举对于位置i, 是否存在f_i + k >= t.size()就行
我的ntt板子常数大,换个常数小或者用fft应该就能过//我直接玄学剪枝跑出来的
#include <bits/stdc++.h>
#define endl '\n'
#define pb push_back
using namespace std;
using ll = long long;
using db = double;
using pii = pair<int , int>;
const int maxn = 4e6 + 10;
int zm[220][2];
const int mod = 998244353;
const int G = 3;
int n,m,L,R[maxn];
int A[maxn],B[maxn];
ll qpow(ll a,ll b)
{
ll ans = 1;
while(b>0)
{
if(b&1) ans = ans*a%mod;
b>>=1;
a = a*a%mod;
}
return ans%mod;
}
void NTT(int *a,int f)
{
for(int i = 0; i < n; i++)
{
if(i < R[i]) swap(a[i],a[R[i]]);
}
for(int i = 1; i < n; i <<= 1)
{
ll gn = qpow(G,(mod - 1) / (i << 1));
for(int j = 0; j < n; j += (i << 1))
{
ll g = 1;
for(int k = 0; k < i; k++, g = g * gn % mod)
{
int x = a[j + k], y = g * a[j + k + i] % mod;
a[j + k] = (x + y) % mod;
a[j + k + i] = (x - y + mod) % mod;
}
}
}
if(f==1) return;
int inv = qpow(n,mod - 2);
reverse(a + 1,a + n);
for(int i = 0; i < n; i++) a[i] = 1ll * a[i] * inv % mod;
}
void solve(int *A,int *B)
{
m = n + m;
L = 0;
for(n = 1; n <= m; n <<= 1) L++;
for(int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
NTT(A,1);
NTT(B,1);
for(int i = 0; i < n; i++) A[i] = 1ll * A[i] * B[i] % mod;
NTT(A,-1);
}
int ans[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int i, j, k;
cin >> k;
string s, t;
cin >> s >> t;
for (auto c : s)
zm[c][0]++;
for (auto c : t)
zm[c][1]++;
int ty = 0;
for (i = 0; i < 220; i++)
{
if (zm[i][0] && zm[i][1])
{
for (j = 0; j < n; j++) A[j] = B[j] = 0;
n = s.size(), m = t.size();
for (j = 0; j < n; j++)
A[j] = s[j] == i;
for (j = 0; j < m; j++)
B[m - 1 - j] = t[j] == i;
solve(A, B);
int nn = s.size(), mm = t.size();
for (int t = mm - 1; t < nn; t++)
ans[t - mm + 1] += A[t];
ty += 20 * nn;
}
if (ty > 80000000)
break;
}
bool flag = 0;
for (i = 0; i < s.size(); i++)
if (ans[i] + k >= t.size())
flag = 1, cout << i + 1 << ' ';
if (!flag)
cout << -1;
return 0;
}