Problem:
F: 部分文字列分解
問題
2 つの文字列
S
と
T
および整数
k
が与えられる。
T
の長さ
k
以上の連続する部分文字列を考えたとき、それらの連結で
S
を構成できるか判定せよ。
ここで文字列
s = s_1 s_2 ... s_n
の連続する部分文字列
s[l, r] = s_l s_{l+1} ... s_r
(1 \leq l \leq r \leq n)
とは、
s
の
l
文字目から
r
文字目までを切り出してできる文字列を指し、その長さは
r - l + 1
である。
入力形式
S
T
k
制約
S
と
T
は小文字アルファベットからなる
1 \leq |S|, |T| \leq 2\times 10^5
1 \leq k \leq |T|
出力形式
S
を構成できるとき
Yes
を、そうでないとき
No
を一行に出力せよ。
入力例1
abracadabra
cadabra
4
出力例1
Yes
T
の長さ
4
以上の部分文字列である
abra
と
cadabra
を連結させることで
abracadabra
が構成でき、これは
S
と等しい文字列である。
入力例2
abcd
zcba
1
出力例2
No
入力例3
abc
zcba
1
出力例3
Yes
入力例4
abcdefg
abcddefg
4
出力例4
No

Submitted solutions:

code_snippet: // AOJ #3112 Substring Decomposition
// 2025.3.21

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct st {
    int l, link;
    int nx[26];
    st() : l(0), link(-1) {
        for(int i=0; i<26; i++) nx[i] = -1;
    }
};

vector<st> sa;

void build_sa(const string &s) {
    int sz = 1, last = 0;
    sa.clear();
    sa.resize(2 * s.size());
    sa[0].l = 0;
    sa[0].link = -1;
    for (int i = 0; i < (int)s.size(); i++){
        int c = s[i] - 'a';
        int cur = sz++;
        sa[cur].l = sa[last].l + 1;
        for (int j = 0; j < 26; j++) sa[cur].nx[j] = -1;

        int p = last;
        while(p != -1 && sa[p].nx[c] == -1) {
            sa[p].nx[c] = cur;
            p = sa[p].link;
        }
        if(p == -1) sa[cur].link = 0;
        else {
            int q = sa[p].nx[c];
            if(sa[p].l + 1 == sa[q].l) sa[cur].link = q;
            else {
                int cl = sz++;
                sa[cl].l = sa[p].l + 1;
                for (int j = 0; j < 26; j++)
                    sa[cl].nx[j] = sa[q].nx[j];
                sa[cl].link = sa[q].link;
                while(p != -1 && sa[p].nx[c] == q){
                    sa[p].nx[c] = cl;
                    p = sa[p].link;
                }
                sa[q].link = sa[cur].link = cl;
            }
        }
        last = cur;
    }
    sa.resize(sz);
}

struct BIT {
    int n;
    vector<int> bit;
    BIT(int n_) : n(n_), bit(n_+1, 0) {}
    void upd(int i, int v) {
        for(; i <= n; i += i & -i) bit[i] += v;
    }
    int sum(int i) {
        int s = 0;
        for(; i > 0; i -= i & -i) s += bit[i];
        return s;
    }
    int query(int l, int r) {
        if(l > r) return 0;
        return sum(r) - sum(l-1);
    }
};

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    string S, T;
    int k;
    cin >> S >> T >> k;
    int n = S.size();

    build_sa(T);

    vector<int> f(n, 0);
    int cur = 0, l = 0;
    for (int i = 0; i < n; i++){
        int c = S[i]-'a';
        if(sa[cur].nx[c] != -1){
            cur = sa[cur].nx[c];
            l++;
        } else {
            while(cur != -1 && sa[cur].nx[c] == -1) cur = sa[cur].link;
            if(cur == -1) cur = 0, l = 0;
            else {
                l = sa[cur].l + 1;
                cur = sa[cur].nx[c];
            }
        }
        f[i] = l;
    }

    vector<int> f_start(n, 0);
    int L = 0;
    for (int i = 0; i < n; i++){
        if(L > 0) L--;
        while(i + L < n && f[i + L] >= L + 1) L++;
        f_start[i] = L;
    }

    vector<int> dp(n+1, 0);
    dp[n] = 1;
    BIT bit(n+1);
    bit.upd(n+1, 1);

    for (int i = n-1; i >= 0; i--){
        int maxL = f_start[i];
        int lim = min(maxL, n - i);
        if(lim < k) dp[i] = 0;
        else {
            if(bit.query(i + k + 1, i + lim + 1) > 0) dp[i] = 1;
            else dp[i] = 0;
        }
        if(dp[i]) bit.upd(i + 1, 1);
    }
    cout << (dp[0] ? "Yes" : "No") << endl;
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 49772
final_rank: 10

code_snippet: // AOJ #3112 Substring Decomposition
// 2025.3.21

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct st {
    int len, link;
    int nx[26];
    st() : len(0), link(-1) {
        for (int i=0; i<26; i++) nx[i] = -1;
    }
};

vector<st> sa;

void build_sa(const string &s) {
    int sz = 1, last = 0;
    sa.resize(2 * s.size());
    sa[0].len = 0;
    sa[0].link = -1;
    for (int i = 0; i < (int)s.size(); i++) {
        int c = s[i]-'a';
        int cur = sz++;
        sa[cur].len = sa[last].len + 1;
        for (int j = 0; j < 26; j++) sa[cur].nx[j] = -1;

        int p = last;
        while (p != -1 && sa[p].nx[c] == -1) {
            sa[p].nx[c] = cur;
            p = sa[p].link;
        }
        if (p == -1) sa[cur].link = 0;
        else {
            int q = sa[p].nx[c];
            if (sa[p].len + 1 == sa[q].len) sa[cur].link = q;
            else {
                int cl = sz++;
                sa[cl].len = sa[p].len + 1;
                for (int j = 0; j < 26; j++) sa[cl].nx[j] = sa[q].nx[j];
                sa[cl].link = sa[q].link;
                while (p != -1 && sa[p].nx[c] == q) {
                    sa[p].nx[c] = cl;
                    p = sa[p].link;
                }
                sa[q].link = sa[cur].link = cl;
            }
        }
        last = cur;
    }
    sa.resize(sz);
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    string S, T;
    int k;
    cin >> S >> T >> k;
    int n = S.size();

    string RT = T;
    reverse(RT.begin(), RT.end());
    string RS = S;
    reverse(RS.begin(), RS.end());

    sa.clear();
    build_sa(RT);

    vector<int> dp(RS.size(), 0);
    int cur = 0, l = 0;
    for (int i = 0; i < (int)RS.size(); i++){
        int c = RS[i]-'a';
        if(sa[cur].nx[c] != -1){
            cur = sa[cur].nx[c];
            l++;
        } else {
            while(cur != -1 && sa[cur].nx[c] == -1) cur = sa[cur].link;
            if(cur == -1) cur = 0, l = 0;
            else {
                l = sa[cur].len + 1;
                cur = sa[cur].nx[c];
            }
        }
        dp[i] = l;
    }

    int pos = 0;
    while(pos < n){
        int L = dp[n-1-pos];
        if(L < k){
            cout << "No" << endl;
            return 0;
        }
        pos += L;
    }
    cout << (pos == n ? "Yes" : "No") << endl;
    return 0;
}
accuracy: 0.039603960396039604
time_ms: 10
memory_kb: 38200
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<ll, P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 62;
constexpr ll MOD = 1000000007;
// constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-10;
const double PI = acos(-1);

#define ALL(v) (v).begin(), (v).end()
#define REP(i, n) for (int i = 0, i_len = n; i < i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }

vector<int> suffix_array(const string& str) {
    int n = str.size();
    vector<int> sa(n + 1), rank(n + 1, -1);  // sa[i] = 辞書順でi番目であるsuffixの開始位置
    iota(sa.begin(), sa.end(), 0);
    for (int i = 0; i < n; i++) rank[i] = str[i];
    int k;
    auto comp = [&](const int& i, const int& j) {
        if (rank[i] != rank[j]) {
            return rank[i] < rank[j];
        } else {
            int ri = i + k <= n ? rank[i + k] : -1;
            int rj = j + k <= n ? rank[j + k] : -1;
            return ri < rj;
        }
    };
    for (k = 1; k <= n; k <<= 1) {
        sort(sa.begin(), sa.end(), comp);
        vector<int> tmp(n + 1, 0);
        for (int i = 0; i < n; i++) {
            tmp[sa[i + 1]] = tmp[sa[i]];
            if (comp(sa[i], sa[i + 1])) tmp[sa[i + 1]]++;
        }
        rank = tmp;
    }
    return sa;
}

vector<int> lcp_array(const string& s, const vector<int>& sa) {
    int n = s.size();
    vector<int> lcp(n), rank(n + 1);  // rank[i]=s[i,n)の辞書順位
    for (int i = 0; i <= n; i++) rank[sa[i]] = i;
    for (int i = 0, len = 0; i < n; i++) {
        int j = sa[rank[i] - 1];  // s[i,n)より辞書順で1つ小さいsuffixの先頭位置
        if (len > 0) len--;
        while (max(i, j) + len < n && s[i + len] == s[j + len]) len++;
        lcp[rank[i] - 1] = len;
    }
    return lcp;
}

int solve() {
    string s, t;
    int k;
    cin >> s >> t >> k;
    string u = s + "~" + t;
    vector<int> sa = suffix_array(u);
    vector<int> lcp = lcp_array(u, sa);
    int n = s.size();
    vector<int> len(n, 0);
    for(int i = 0, h = 0; i < int(u.size()); i++){
        if(sa[i] < n){
            len[sa[i]] = max(len[sa[i]], h);
            h = min(h, lcp[i]);
        } else {
            h = lcp[i];
        }
    }
    for(int i = int(u.size()) - 1, h = 0; i >= 0; i--){
        if(sa[i] < n){
            h = min(h, lcp[i]);
            len[sa[i]] = max(len[sa[i]], h);
        } else if (i > 0) {
            h = lcp[i-1];
        }
    }
    vector<int> dp(n+2, 0);
    dp[0] = 1;
    dp[1] = -1;
    for(int i=0;i<n;i++){
        if(dp[i] > 0 && len[i] >= k){
            dp[i+k]++;
            dp[i+len[i]+1]--;
        }
        dp[i+1] += dp[i];
    }
    cout << (dp[n] > 0 ? "Yes" : "No") << endl;
    return 0;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    solve();
    // while(!solve());
    return 0;
}
accuracy: 1
time_ms: 280
memory_kb: 8492
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<ll, P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 62;
constexpr ll MOD = 1000000007;
// constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-10;
const double PI = acos(-1);

#define ALL(v) (v).begin(), (v).end()
#define REP(i, n) for (int i = 0, i_len = n; i < i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }


vector<int> suffix_array(const string& str) {
    int n = str.size();
    vector<int> sa(n + 1), rank(n + 1, -1);  // sa[i] = 辞書順でi番目であるsuffixの開始位置
    iota(sa.begin(), sa.end(), 0);
    for (int i = 0; i < n; i++) rank[i] = str[i];
    int k;
    auto comp = [&](const int& i, const int& j) {
        if (rank[i] != rank[j]) {
            return rank[i] < rank[j];
        } else {
            int ri = i + k <= n ? rank[i + k] : -1;
            int rj = j + k <= n ? rank[j + k] : -1;
            return ri < rj;
        }
    };
    for (k = 1; k <= n; k <<= 1) {
        sort(sa.begin(), sa.end(), comp);
        vector<int> tmp(n + 1, 0);
        for (int i = 0; i < n; i++) {
            tmp[sa[i + 1]] = tmp[sa[i]];
            if (comp(sa[i], sa[i + 1])) tmp[sa[i + 1]]++;
        }
        rank = tmp;
    }
    return sa;
}

vector<int> lcp_array(const string& s, const vector<int>& sa) {
    int n = s.size();
    vector<int> lcp(n), rank(n + 1);  // rank[i]=s[i,n)の辞書順位
    for (int i = 0; i <= n; i++) rank[sa[i]] = i;
    for (int i = 0, len = 0; i < n; i++) {
        int j = sa[rank[i] - 1];  // s[i,n)より辞書順で1つ小さいsuffixの先頭位置
        if (len > 0) len--;
        while (max(i, j) + len < n && s[i + len] == s[j + len]) len++;
        lcp[rank[i] - 1] = len;
    }
    return lcp;
}

int solve() {
    string s, t;
    int k;
    cin >> s >> t >> k;
    string u = s + "~" + t;
    vector<int> sa = suffix_array(u);
    vector<int> lcp = lcp_array(u, sa);
    int n = s.size();
    vector<int> len(n, 0);
    for(int i = 1; i < int(u.size()); i++){
        if(sa[i] < n){
            len[sa[i]] = max(lcp[i-1], lcp[i]);
        }
    }
    vector<int> dp(n+2, 0);
    dp[0] = 1;
    dp[1] = -1;
    for(int i=0;i<n;i++){
        if(dp[i] > 0 && len[i] >= k){
            dp[i+k]++;
            dp[i+len[i]+1]--;
        }
        dp[i+1] += dp[i];
    }
    cout << (dp[n] > 0 ? "Yes" : "No") << endl;
    return 0;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    solve();
    // while(!solve());
    return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 8456
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<ll, P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 62;
constexpr ll MOD = 1000000007;
// constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-10;
const double PI = acos(-1);

#define ALL(v) (v).begin(), (v).end()
#define REP(i, n) for (int i = 0, i_len = n; i < i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }


vector<int> suffix_array(const string& str) {
    int n = str.size();
    vector<int> sa(n + 1), rank(n + 1, -1);  // sa[i] = 辞書順でi番目であるsuffixの開始位置
    iota(sa.begin(), sa.end(), 0);
    for (int i = 0; i < n; i++) rank[i] = str[i];
    int k;
    auto comp = [&](const int& i, const int& j) {
        if (rank[i] != rank[j]) {
            return rank[i] < rank[j];
        } else {
            int ri = i + k <= n ? rank[i + k] : -1;
            int rj = j + k <= n ? rank[j + k] : -1;
            return ri < rj;
        }
    };
    for (k = 1; k <= n; k <<= 1) {
        sort(sa.begin(), sa.end(), comp);
        vector<int> tmp(n + 1, 0);
        for (int i = 0; i < n; i++) {
            tmp[sa[i + 1]] = tmp[sa[i]];
            if (comp(sa[i], sa[i + 1])) tmp[sa[i + 1]]++;
        }
        rank = tmp;
    }
    return sa;
}

vector<int> lcp_array(const string& s, const vector<int>& sa) {
    int n = s.size();
    vector<int> lcp(n), rank(n + 1);  // rank[i]=s[i,n)の辞書順位
    for (int i = 0; i <= n; i++) rank[sa[i]] = i;
    for (int i = 0, len = 0; i < n; i++) {
        int j = sa[rank[i] - 1];  // s[i,n)より辞書順で1つ小さいsuffixの先頭位置
        if (len > 0) len--;
        while (max(i, j) + len < n && s[i + len] == s[j + len]) len++;
        lcp[rank[i] - 1] = len;
    }
    return lcp;
}

int solve() {
    string s, t;
    int k;
    cin >> s >> t >> k;
    string u = s + "~" + t;
    vector<int> sa = suffix_array(u);
    vector<int> lcp = lcp_array(u, sa);
    int n = s.size();
    vector<int> len(n, 0);
    for(int i = 1; i < int(u.size()); i++){
        if(sa[i] < n){
            len[sa[i]] = max(lcp[i-1], lcp[i]);
        }
    }
    vector<int> dp(n+1, 0);
    dp[0] = 1;
    dp[1] = -1;
    for(int i=0;i<n;i++){
        if(dp[i] > 0 && len[i] >= k){
            dp[i+k]++;
            dp[i+len[i]+1]--;
        }
        dp[i+1] += dp[i];
    }
    cout << (dp[n] > 0 ? "Yes" : "No") << endl;
    return 0;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    solve();
    // while(!solve());
    return 0;
}
accuracy: 0.1782178217821782
time_ms: 250
memory_kb: 8140
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const ll mod=1e9+7;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}
template<class T> T min(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;}
template<class T> T max(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;}

namespace atcoder {

namespace internal {

std::vector<int> sa_naive(const std::vector<int>& s) {
    int n = int(s.size());
    std::vector<int> sa(n);
    std::iota(sa.begin(), sa.end(), 0);
    std::sort(sa.begin(), sa.end(), [&](int l, int r) {
        if (l == r) return false;
        while (l < n && r < n) {
            if (s[l] != s[r]) return s[l] < s[r];
            l++;
            r++;
        }
        return l == n;
    });
    return sa;
}

std::vector<int> sa_doubling(const std::vector<int>& s) {
    int n = int(s.size());
    std::vector<int> sa(n), rnk = s, tmp(n);
    std::iota(sa.begin(), sa.end(), 0);
    for (int k = 1; k < n; k *= 2) {
        auto cmp = [&](int x, int y) {
            if (rnk[x] != rnk[y]) return rnk[x] < rnk[y];
            int rx = x + k < n ? rnk[x + k] : -1;
            int ry = y + k < n ? rnk[y + k] : -1;
            return rx < ry;
        };
        std::sort(sa.begin(), sa.end(), cmp);
        tmp[sa[0]] = 0;
        for (int i = 1; i < n; i++) {
            tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
        }
        std::swap(tmp, rnk);
    }
    return sa;
}

// SA-IS, linear-time suffix array construction
// Reference:
// G. Nong, S. Zhang, and W. H. Chan,
// Two Efficient Algorithms for Linear Time Suffix Array Construction
template <int THRESHOLD_NAIVE = 10, int THRESHOLD_DOUBLING = 40>
std::vector<int> sa_is(const std::vector<int>& s, int upper) {
    int n = int(s.size());
    if (n == 0) return {};
    if (n == 1) return {0};
    if (n == 2) {
        if (s[0] < s[1]) {
            return {0, 1};
        } else {
            return {1, 0};
        }
    }
    if (n < THRESHOLD_NAIVE) {
        return sa_naive(s);
    }
    if (n < THRESHOLD_DOUBLING) {
        return sa_doubling(s);
    }

    std::vector<int> sa(n);
    std::vector<bool> ls(n);
    for (int i = n - 2; i >= 0; i--) {
        ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
    }
    std::vector<int> sum_l(upper + 1), sum_s(upper + 1);
    for (int i = 0; i < n; i++) {
        if (!ls[i]) {
            sum_s[s[i]]++;
        } else {
            sum_l[s[i] + 1]++;
        }
    }
    for (int i = 0; i <= upper; i++) {
        sum_s[i] += sum_l[i];
        if (i < upper) sum_l[i + 1] += sum_s[i];
    }

    auto induce = [&](const std::vector<int>& lms) {
        std::fill(sa.begin(), sa.end(), -1);
        std::vector<int> buf(upper + 1);
        std::copy(sum_s.begin(), sum_s.end(), buf.begin());
        for (auto d : lms) {
            if (d == n) continue;
            sa[buf[s[d]]++] = d;
        }
        std::copy(sum_l.begin(), sum_l.end(), buf.begin());
        sa[buf[s[n - 1]]++] = n - 1;
        for (int i = 0; i < n; i++) {
            int v = sa[i];
            if (v >= 1 && !ls[v - 1]) {
                sa[buf[s[v - 1]]++] = v - 1;
            }
        }
        std::copy(sum_l.begin(), sum_l.end(), buf.begin());
        for (int i = n - 1; i >= 0; i--) {
            int v = sa[i];
            if (v >= 1 && ls[v - 1]) {
                sa[--buf[s[v - 1] + 1]] = v - 1;
            }
        }
    };

    std::vector<int> lms_map(n + 1, -1);
    int m = 0;
    for (int i = 1; i < n; i++) {
        if (!ls[i - 1] && ls[i]) {
            lms_map[i] = m++;
        }
    }
    std::vector<int> lms;
    lms.reserve(m);
    for (int i = 1; i < n; i++) {
        if (!ls[i - 1] && ls[i]) {
            lms.push_back(i);
        }
    }

    induce(lms);

    if (m) {
        std::vector<int> sorted_lms;
        sorted_lms.reserve(m);
        for (int v : sa) {
            if (lms_map[v] != -1) sorted_lms.push_back(v);
        }
        std::vector<int> rec_s(m);
        int rec_upper = 0;
        rec_s[lms_map[sorted_lms[0]]] = 0;
        for (int i = 1; i < m; i++) {
            int l = sorted_lms[i - 1], r = sorted_lms[i];
            int end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n;
            int end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n;
            bool same = true;
            if (end_l - l != end_r - r) {
                same = false;
            } else {
                while (l < end_l) {
                    if (s[l] != s[r]) {
                        break;
                    }
                    l++;
                    r++;
                }
                if (l == n || s[l] != s[r]) same = false;
            }
            if (!same) rec_upper++;
            rec_s[lms_map[sorted_lms[i]]] = rec_upper;
        }

        auto rec_sa =
            sa_is<THRESHOLD_NAIVE, THRESHOLD_DOUBLING>(rec_s, rec_upper);

        for (int i = 0; i < m; i++) {
            sorted_lms[i] = lms[rec_sa[i]];
        }
        induce(sorted_lms);
    }
    return sa;
}

}  // namespace internal

std::vector<int> suffix_array(const std::vector<int>& s, int upper) {
    assert(0 <= upper);
    for (int d : s) {
        assert(0 <= d && d <= upper);
    }
    auto sa = internal::sa_is(s, upper);
    return sa;
}

template <class T> std::vector<int> suffix_array(const std::vector<T>& s) {
    int n = int(s.size());
    std::vector<int> idx(n);
    iota(idx.begin(), idx.end(), 0);
    sort(idx.begin(), idx.end(), [&](int l, int r) { return s[l] < s[r]; });
    std::vector<int> s2(n);
    int now = 0;
    for (int i = 0; i < n; i++) {
        if (i && s[idx[i - 1]] != s[idx[i]]) now++;
        s2[idx[i]] = now;
    }
    return internal::sa_is(s2, now);
}

std::vector<int> suffix_array(const std::string& s) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return internal::sa_is(s2, 255);
}

// Reference:
// T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park,
// Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its
// Applications
template <class T>
std::vector<int> lcp_array(const std::vector<T>& s,
                           const std::vector<int>& sa) {
    int n = int(s.size());
    assert(n >= 1);
    std::vector<int> rnk(n);
    for (int i = 0; i < n; i++) {
        rnk[sa[i]] = i;
    }
    std::vector<int> lcp(n - 1);
    int h = 0;
    for (int i = 0; i < n; i++) {
        if (h > 0) h--;
        if (rnk[i] == 0) continue;
        int j = sa[rnk[i] - 1];
        for (; j + h < n && i + h < n; h++) {
            if (s[j + h] != s[i + h]) break;
        }
        lcp[rnk[i] - 1] = h;
    }
    return lcp;
}

std::vector<int> lcp_array(const std::string& s, const std::vector<int>& sa) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return lcp_array(s2, sa);
}

// Reference:
// D. Gusfield,
// Algorithms on Strings, Trees, and Sequences: Computer Science and
// Computational Biology
template <class T> std::vector<int> z_algorithm(const std::vector<T>& s) {
    int n = int(s.size());
    if (n == 0) return {};
    std::vector<int> z(n);
    z[0] = 0;
    for (int i = 1, j = 0; i < n; i++) {
        int& k = z[i];
        k = (j + z[j] <= i) ? 0 : std::min(j + z[j] - i, z[i - j]);
        while (i + k < n && s[k] == s[i + k]) k++;
        if (j + z[j] < i + z[i]) j = i;
    }
    z[0] = n;
    return z;
}

std::vector<int> z_algorithm(const std::string& s) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return z_algorithm(s2);
}

}  // namespace atcoder

using atcoder::lcp_array;
using atcoder::suffix_array;
using atcoder::z_algorithm;


namespace po167{
template <class T,T (*op)(T,T),T(*e)()>
struct segment_tree{
	int _n,size;
	std::vector<T> seg;
	int ceil_pow2(int a){
		int b=1;
		while(a>b){
			b<<=1;
		}
		return b;
	}
	void update(int k){seg[k]=op(seg[k*2],seg[k*2+1]);};
	segment_tree(int n) :_n(n){
		size=ceil_pow2(n);
		seg=std::vector<T>(size*2,e());
	}
	segment_tree(std::vector<T> &p) :_n((int) p.size()){
		size=ceil_pow2(_n);
		seg=std::vector<T>(size*2,e());
		for(int i=0;i<_n;i++) seg[i+size]=p[i];
		for(int i=size-1;i>0;i--) update(i);
	}
	void set(int ind,T val){
		assert(0<=ind&&ind<_n);
		ind+=size;
		seg[ind]=val;
		while(ind!=1){
			ind>>=1;
			update(ind);
		}
	}
    void addl(int ind,T val){
        set(ind,op(get(ind),val));
    }
    void addr(int ind,T val){
        set(ind,op(val,get(ind)));
    }
	T get(int ind){
		assert(0<=ind&&ind<_n);
		return seg[ind+size];
	}
	T query(int l,int r){
		assert(0<=l&&l<=r&&r<=_n);
		T l_val=e();
		T r_val=e();
		l+=size,r+=size;
		while(l<r){
			if(l&1) l_val=op(l_val,seg[l]),l+=1;
			if(r&1) r-=1,r_val=op(seg[r],r_val);
			r>>=1;
			l>>=1;
		}
		return op(l_val,r_val);
	}
	template <bool (*f)(T)> int max_right(int l) {
        return max_right(l, [](T x) { return f(x); });
    }
	template <class F> int max_right(int l, F f) {
		assert(0<=l&&l<=_n);
		assert(f(e()));
		if(f(query(l,_n))) return _n;
		T val=e();
		l+=size;
		while(true){
			while(l%2==0) l>>=1;
			if(!f(op(val,seg[l]))){
				while(l<size){
					l*=2;
					if(f(op(val,seg[l]))){
						val=op(val,seg[l]);
						l++;
					}
				}
				return l-size;
			}
			val=op(val,seg[l]);
			l++;
		}
	}
	template <bool (*f)(T)> int min_left(int r) {
        return min_left(r, [](T x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        T sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(seg[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(seg[r], sm))) {
                        sm = op(seg[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(seg[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

};
}
using po167::segment_tree;


using F= int;
F op(F a,F b){return min(a,b);}
F e(){return INF;}


void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	string S,T;
	cin>>S>>T;
	int k;
	cin>>k;
	int N=S.size(),M=T.size();
	string U=S+(char)('z'+1)+T;
	auto sa=suffix_array(U);
	auto lc=lcp_array(U,sa);
	int f=-1;
	vector<int> rev(N+M+1);
	rep(i,N+M+1) rev[sa[i]]=i;
	vector<int> step(N);
	segment_tree<F,op,e> seg(lc);
	rep(i,N+M){
		if(sa[i]<N){
			if(f!=-1) chmax(step[sa[i]],seg.query(f,i));
		}else if(sa[i]!=N){
			f=i;
		}
	}
	f=-1;
	for(int i=N+M-1;i>=0;i--){
		if(sa[i]<N){
			if(f!=-1) chmax(step[sa[i]],seg.query(i,f));
		}else if(sa[i]!=N){
			f=i;
		}
	}
	vector<int> dp(N+1);
	dp[0]=1;
	dp[1]=-1;
	//vec_out(step);
	rep(i,N){
		//cout<<i<<" "<<dp[i]<<" "<<step[i]<<"\n";
		dp[i+1]+=dp[i];
		if(dp[i]==0) continue;
		if(step[i]<k) continue;
		if(i+step[i]>=N){
			cout<<"Yes\n";
			return;
		}
		dp[i+k]++;
		dp[i+step[i]+1]--;
	}
	cout<<"No\n";
}
accuracy: 1
time_ms: 20
memory_kb: 17076
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
/*
#include <atcoder/all>
using namespace atcoder;
*/
#define all(hoge) (hoge).begin(), (hoge).end()
#define en '\n'
using ll = long long;
using ull = unsigned long long;
#define rep(i, m, n) for(ll i = (ll)(m); i < (ll)(n); ++i)
#define rep2(i, m, n) for(ll i = (ll)(n)-1; i >= (ll)(m); --i)
#define REP(i, n) rep(i, 0, n)
#define REP2(i, n) rep2(i, 0, n)
template <class T>
using vec = vector<T>;
template <class T>
using vvec = vector<vec<T>>;
typedef pair<ll, ll> P;
using tp = tuple<ll, ll, ll>;

constexpr long long INF = 1LL << 60;
constexpr int INF_INT = 1 << 25;
constexpr long long MOD = (ll)1e9 + 7;
//constexpr long long MOD = 998244353LL;
using ld = long double;
static const ld pi = 3.141592653589793L;

using Array = vector<ll>;
using Matrix = vector<Array>;

/*
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
*/

template <class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

std::vector<int> sa_naive(const std::vector<int> &s) {
    int n = int(s.size());
    std::vector<int> sa(n);
    std::iota(sa.begin(), sa.end(), 0);
    std::sort(sa.begin(), sa.end(), [&](int l, int r) {
        if(l == r)
            return false;
        while(l < n && r < n) {
            if(s[l] != s[r])
                return s[l] < s[r];
            l++;
            r++;
        }
        return l == n;
    });
    return sa;
}

std::vector<int> sa_doubling(const std::vector<int> &s) {
    int n = int(s.size());
    std::vector<int> sa(n), rnk = s, tmp(n);
    std::iota(sa.begin(), sa.end(), 0);
    for(int k = 1; k < n; k *= 2) {
        auto cmp = [&](int x, int y) {
            if(rnk[x] != rnk[y])
                return rnk[x] < rnk[y];
            int rx = x + k < n ? rnk[x + k] : -1;
            int ry = y + k < n ? rnk[y + k] : -1;
            return rx < ry;
        };
        std::sort(sa.begin(), sa.end(), cmp);
        tmp[sa[0]] = 0;
        for(int i = 1; i < n; i++) {
            tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
        }
        std::swap(tmp, rnk);
    }
    return sa;
}

// SA-IS, linear-time suffix array construction
// Reference:
// G. Nong, S. Zhang, and W. H. Chan,
// Two Efficient Algorithms for Linear Time Suffix Array Construction
template <int THRESHOLD_NAIVE = 10, int THRESHOLD_DOUBLING = 40>
std::vector<int> sa_is(const std::vector<int> &s, int upper) {
    int n = int(s.size());
    if(n == 0)
        return {};
    if(n == 1)
        return {0};
    if(n == 2) {
        if(s[0] < s[1]) {
            return {0, 1};
        } else {
            return {1, 0};
        }
    }
    if(n < THRESHOLD_NAIVE) {
        return sa_naive(s);
    }
    if(n < THRESHOLD_DOUBLING) {
        return sa_doubling(s);
    }

    std::vector<int> sa(n);
    std::vector<bool> ls(n);
    for(int i = n - 2; i >= 0; i--) {
        ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
    }
    std::vector<int> sum_l(upper + 1), sum_s(upper + 1);
    for(int i = 0; i < n; i++) {
        if(!ls[i]) {
            sum_s[s[i]]++;
        } else {
            sum_l[s[i] + 1]++;
        }
    }
    for(int i = 0; i <= upper; i++) {
        sum_s[i] += sum_l[i];
        if(i < upper)
            sum_l[i + 1] += sum_s[i];
    }

    auto induce = [&](const std::vector<int> &lms) {
        std::fill(sa.begin(), sa.end(), -1);
        std::vector<int> buf(upper + 1);
        std::copy(sum_s.begin(), sum_s.end(), buf.begin());
        for(auto d : lms) {
            if(d == n)
                continue;
            sa[buf[s[d]]++] = d;
        }
        std::copy(sum_l.begin(), sum_l.end(), buf.begin());
        sa[buf[s[n - 1]]++] = n - 1;
        for(int i = 0; i < n; i++) {
            int v = sa[i];
            if(v >= 1 && !ls[v - 1]) {
                sa[buf[s[v - 1]]++] = v - 1;
            }
        }
        std::copy(sum_l.begin(), sum_l.end(), buf.begin());
        for(int i = n - 1; i >= 0; i--) {
            int v = sa[i];
            if(v >= 1 && ls[v - 1]) {
                sa[--buf[s[v - 1] + 1]] = v - 1;
            }
        }
    };

    std::vector<int> lms_map(n + 1, -1);
    int m = 0;
    for(int i = 1; i < n; i++) {
        if(!ls[i - 1] && ls[i]) {
            lms_map[i] = m++;
        }
    }
    std::vector<int> lms;
    lms.reserve(m);
    for(int i = 1; i < n; i++) {
        if(!ls[i - 1] && ls[i]) {
            lms.push_back(i);
        }
    }

    induce(lms);

    if(m) {
        std::vector<int> sorted_lms;
        sorted_lms.reserve(m);
        for(int v : sa) {
            if(lms_map[v] != -1)
                sorted_lms.push_back(v);
        }
        std::vector<int> rec_s(m);
        int rec_upper = 0;
        rec_s[lms_map[sorted_lms[0]]] = 0;
        for(int i = 1; i < m; i++) {
            int l = sorted_lms[i - 1], r = sorted_lms[i];
            int end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n;
            int end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n;
            bool same = true;
            if(end_l - l != end_r - r) {
                same = false;
            } else {
                while(l < end_l) {
                    if(s[l] != s[r]) {
                        break;
                    }
                    l++;
                    r++;
                }
                if(l == n || s[l] != s[r])
                    same = false;
            }
            if(!same)
                rec_upper++;
            rec_s[lms_map[sorted_lms[i]]] = rec_upper;
        }

        auto rec_sa =
            sa_is<THRESHOLD_NAIVE, THRESHOLD_DOUBLING>(rec_s, rec_upper);

        for(int i = 0; i < m; i++) {
            sorted_lms[i] = lms[rec_sa[i]];
        }
        induce(sorted_lms);
    }
    return sa;
}

std::vector<int> suffix_array(const std::vector<int> &s, int upper) {
    assert(0 <= upper);
    for(int d : s) {
        assert(0 <= d && d <= upper);
    }
    auto sa = sa_is(s, upper);
    return sa;
}

template <class T>
std::vector<int> suffix_array(const std::vector<T> &s) {
    int n = int(s.size());
    std::vector<int> idx(n);
    iota(idx.begin(), idx.end(), 0);
    sort(idx.begin(), idx.end(), [&](int l, int r) { return s[l] < s[r]; });
    std::vector<int> s2(n);
    int now = 0;
    for(int i = 0; i < n; i++) {
        if(i && s[idx[i - 1]] != s[idx[i]])
            now++;
        s2[idx[i]] = now;
    }
    return sa_is(s2, now);
}

std::vector<int> suffix_array(const std::string &s) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for(int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return sa_is(s2, 255);
}

// Reference:
// T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park,
// Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its
// Applications
template <class T>
std::vector<int> lcp_array(const std::vector<T> &s,
                           const std::vector<int> &sa) {
    int n = int(s.size());
    assert(n >= 1);
    std::vector<int> rnk(n);
    for(int i = 0; i < n; i++) {
        rnk[sa[i]] = i;
    }
    std::vector<int> lcp(n - 1);
    int h = 0;
    for(int i = 0; i < n; i++) {
        if(h > 0)
            h--;
        if(rnk[i] == 0)
            continue;
        int j = sa[rnk[i] - 1];
        for(; j + h < n && i + h < n; h++) {
            if(s[j + h] != s[i + h])
                break;
        }
        lcp[rnk[i] - 1] = h;
    }
    return lcp;
}

std::vector<int> lcp_array(const std::string &s, const std::vector<int> &sa) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for(int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return lcp_array(s2, sa);
}

void solve() {
    string s, t;
    cin >> s >> t;
    int k;
    cin >> k;
    int n = s.size();
    s += '#' + t;
    auto sa = suffix_array(s);
    auto lcp = lcp_array(s, sa);

    vec<ll> lcs(n, 0);
    //s.substr(i)の最長共通部分文字列を前計算
    //sは直近のtとの最長共通部分文字列だけ考えればいい
    {
        ll tmp = INF;
        if(sa[0] < n)
            tmp = 0;
        REP(i, lcp.size()) {
            if(sa[i + 1] < n) {
                chmin(tmp, (ll)lcp[i]);
                chmax(lcs[sa[i + 1]], tmp);
            } else {
                tmp = INF;
            }
        }
    }
    {
        ll tmp = INF;
        if(sa[sa.size() - 1] < n)
            tmp = 0;
        REP2(i, lcp.size()) {
            if(sa[i] < n) {
                chmin(tmp, (ll)lcp[i]);
                chmax(lcs[sa[i]], tmp);
            } else {
                tmp = INF;
            }
        }
    }

    vec<ll> dp(n + 1, 0);
    vec<ll> imos(n + 2, 0);
    dp[0] = 1;
    REP(i, n) {
        dp[i] += imos[i];
        imos[i + 1] += imos[i];
        if(dp[i] <= 0)
            continue;
        if(lcs[i] < k)
            continue;
        imos[i + k]++;
        imos[i + lcs[i] + 1]--;
    }
    dp[n] += imos[n];

    if(dp[n])
        cout << "Yes" << en;
    else
        cout << "No" << en;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    /*
    ll t;
    cin >> t;
    REP(i, t - 1) {
        solve();
    }*/

    solve();

    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 12484
final_rank: 1

code_snippet: #include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <functional>
#include <bitset>

using namespace std;
using lint = long long int;
long long int INF = 1001001001001001LL;
int inf = 1000000007;
long long int MOD = 1000000007LL;
double PI = 3.1415926535897932;

template<typename T1,typename T2>inline void chmin(T1 &a,const T2 &b){if(a>b) a=b;}
template<typename T1,typename T2>inline void chmax(T1 &a,const T2 &b){if(a<b) a=b;}

#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()

/* do your best */
// 引用：https://ei1333.github.io/luzhiled/snippets/string/suffix-array.html

// quoted from beet-aizu
template <typename T, typename E, typename F, typename G>
struct SegmentTree{
    // using F = function<T(T, T)>
    // using G = function<T(T, E)>
    int n;
    F f;
    G g;
    T ti;
    vector<T> dat;
    SegmentTree(){};
    SegmentTree(F f,G g,T ti):f(f),g(g),ti(ti){}
    void init(int n_){    
        n=1;
        while(n<n_) n<<=1;
        dat.assign(n<<1,ti);
    }
    void build(const vector<T> &v){
        int n_=v.size();
        init(n_);
        for(int i=0;i<n_;i++) dat[n+i]=v[i];
        for(int i=n-1;i;i--)
            dat[i]=f(dat[(i<<1)|0],dat[(i<<1)|1]);
    }
    void update(int k,const E &x){
        k += n;
        dat[k] = g(dat[k], x);
        while(k>>=1)
            dat[k]=f(dat[(k<<1)|0],dat[(k<<1)|1]);    
    }
    T operator [](int k) const { return dat[k+n]; }
    T query(int a,int b) const {
        T vl=ti,vr=ti;
        for(int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
            if(l&1) vl=f(vl,dat[l++]);
            if(r&1) vr=f(dat[--r],vr);
        }
        return f(vl,vr);
    }

    /* TODO わからない 聞く 
    template<typename C>
    int find(int a,int b,C &check,int k,int l,int r){
        if(!check(dat[k])||r<=a||b<=l) return -1;
        if(k>=n) return k-n;
        int m=(l+r)>>1;
        int vl=find(a,b,check,(k<<1)|0,l,m);
        if(~vl) return vl;
        return find(a,b,check,(k<<1)|1,m,r);
    }
    template<typename C>
    int find(int a,int b,C &check){
        return find(a,b,check,1,0,n);
    }*/
    
};


/**  テンプレ
int main(){
  using T = ***;  // type T
  using E = ***;  // type E
  auto f = [](T a, T b){ // return type T value
    return ***;
  };
  auto g = [](T a, E b){ // return type T value
    return ***;  // return b;
  };
  T ti = ***;  // identity element
  SegmentTree<T, E, decltype(f), decltype(g)> sg(f, g, ti);  // don't change
  sg.build(***);
}
**/

struct SuffixArray {
  vector< int > SA;
  const string s;

  SuffixArray(const string &str) : s(str) {
    SA.resize(s.size());
    iota(begin(SA), end(SA), 0);
    sort(begin(SA), end(SA), [&](int a, int b) {
      return s[a] == s[b] ? a > b : s[a] < s[b];
    });
    vector< int > classes(s.size()), c(s.begin(), s.end()), cnt(s.size());
    for(int len = 1; len < s.size(); len <<= 1) {
      for(int i = 0; i < s.size(); i++) {
        if(i > 0 && c[SA[i - 1]] == c[SA[i]] && SA[i - 1] + len < s.size() && c[SA[i - 1] + len / 2] == c[SA[i] + len / 2]) {
          classes[SA[i]] = classes[SA[i - 1]];
        } else {
          classes[SA[i]] = i;
        }
      }
      iota(begin(cnt), end(cnt), 0);
      copy(begin(SA), end(SA), begin(c));
      for(int i = 0; i < s.size(); i++) {
        int s1 = c[i] - len;
        if(s1 >= 0) SA[cnt[classes[s1]]++] = s1;
      }
      classes.swap(c);
    }
  }

  int operator[](int k) const {
    return SA[k];
  }

  size_t size() const {
    return s.size();
  }

  bool lt_substr(const string &t, int si = 0, int ti = 0) {
    int sn = (int) s.size(), tn = (int) t.size();
    while(si < sn && ti < tn) {
      if(s[si] < t[ti]) return true;
      if(s[si] > t[ti]) return false;
      ++si, ++ti;
    }
    return si >= sn && ti < tn;
  }

  int lower_bound(const string &t) {
    int low = -1, high = (int) SA.size();
    while(high - low > 1) {
      int mid = (low + high) / 2;
      if(lt_substr(t, SA[mid])) low = mid;
      else high = mid;
    }
    return high;
  }

  pair< int, int > lower_upper_bound(string &t) {
    int idx = lower_bound(t);
    int low = idx - 1, high = (int) SA.size();
    t.back()++;
    while(high - low > 1) {
      int mid = (low + high) / 2;
      if(lt_substr(t, SA[mid])) low = mid;
      else high = mid;
    }
    t.back()--;
    return {idx, high};
  }

  void output() {
    for(int i = 0; i < size(); i++) {
      cout << i << ": " << s.substr(SA[i]) << " " << SA[i] << endl;
    }
  }
};

struct LongestCommonPrefixArray {
  const SuffixArray &SA;
  vector< int > LCP, rank;

  LongestCommonPrefixArray(const SuffixArray &SA) : SA(SA), LCP(SA.size()) {
    rank.resize(SA.size());
    for(int i = 0; i < SA.size(); i++) {
      rank[SA[i]] = i;
    }
    for(int i = 0, h = 0; i < SA.size(); i++) {
      if(rank[i] + 1 < SA.size()) {
        for(int j = SA[rank[i] + 1]; max(i, j) + h < SA.size() && SA.s[i + h] == SA.s[j + h]; ++h);
        LCP[rank[i] + 1] = h;
        if(h > 0) --h;
      }
    }
  }

  int operator[](int k) const {
    return LCP[k];
  }

  size_t size() const {
    return LCP.size();
  }

  void output() {
    for(int i = 0; i < size(); i++) {
      cout << i << ": " << LCP[i] << " " << SA.s.substr(SA[i]) << " " << SA[i] << endl;
    }
  }

  void solve(int len_s, int len_t, int k) {
    // やること
    // 文字列長をみて，s か t かを判定
    // s に一番近い t を見つける（高々二つ）
    // それらの lcp を計算，max をとる（それより離れたところはダメ（単調性））
    // そのあと DP する
    
    int n = size();
    using T = int;  // type T
    using E = int;  // type E
    auto f = [](T a, T b){ // return type T value
      return min(a, b);
    };
    auto g = [](T a, E b){ // return type T value
      return b;  // return b;
    };
    T ti = inf;  // identity element
    SegmentTree<T, E, decltype(f), decltype(g)> sg(f, g, ti);  // don't change
    sg.build(LCP);

    // 自分より上の id
    vector<int> up(n, -1);
    int id = -1;
    for (int i = 0; i < n; i++) {
      int len = n - SA[i];
      if (len <= len_t) {
        id = i;
      } else if (len > len_t + 1) {
        up[i] = id;
      }
    }

    vector<int> down(n, -1);
    id = -1;
    for (int i = n - 1; i >= 0; i--) {
      int len = n - SA[i];
      if (len <= len_t) {
        id = i;
      } else if (len > len_t + 1) {
        down[i] = id;
      }
    }

    for (int i = 0; i < n; i++) {
      //cerr << up[i] << " " << down[i] << endl;
    }

    vector<int> maxLen(len_s, 0);
    for (int i = 0; i < n; i++) {
      int len = n - SA[i];
      if (len > len_t + 1) {
        lint maxLcp = 0;
        if (down[i] != -1) {
          lint tmp = sg.query(i + 1, down[i] + 1);
          maxLcp = max(tmp, maxLcp);
        }
        if (up[i] != -1) {
          lint tmp = sg.query(up[i] + 1, i + 1);
          maxLcp = max(tmp, maxLcp);
        }

        maxLen[SA[i]] = maxLcp;
      }
    }

    for (int i = 0; i < len_s; i++) {
      //cerr << i << ": " << maxLen[i] << endl;
    }
  
    vector<int> dp(len_s + 2, 0);
    dp[0] = 1;
    dp[1] = -1;
    for (int i = 0; i < len_s; i++) {
      if (i != 0) dp[i] += dp[i - 1];
      //cerr << "i : " << i << " dp[i] = " << dp[i] << endl; 
      if (dp[i] == 0) continue;
      lint maxLcp = maxLen[i];
      //cerr << "maxLcp = " << maxLcp << endl;
      if (maxLcp < k) continue;
      int l = i + k;
      int r = i + maxLcp + 1;
      if (l > len_s) continue;
      r = min(r, len_s + 1);

      //cerr << i << " " << l << " " << r << endl;
      dp[l]++;
      dp[r]--;
    }

    dp[len_s] += dp[len_s - 1];
    
    //for (int i = 0; i <= len_s; i++) {
      //cerr << dp[i] << " ";
    //}
    //cerr << endl;

    if (dp[len_s] >= 1) {
      cout << "Yes" << endl;
    } else {
      cout << "No" << endl;
    }
  }
};

int main() {
  
  string s;
  string t;
  int k;
  cin >> s >> t >> k;

  string str = s + "#" + t;
  SuffixArray sa(str);
  LongestCommonPrefixArray lcp(sa);
  lcp.solve(s.size(), t.size(), k);

  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 17048
final_rank: 3

code_snippet: #include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <stack>
#include <functional>
#include <bitset>
#include <assert.h>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(ll i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = 1<<30;
const ll linf = 1LL<<62;
const int MAX = 510000;
ll dy[8] = {0,1,0,-1,1,-1,1,-1};
ll dx[8] = {1,0,-1,0,1,-1,-1,1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){cout << a << " " << b << "\n";}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
const int mod = 1e9 + 7;
//const int mod = 998244353;


struct SuffixArray{
	vector<int> ran;
	vector<int> tmp;
	vector<int> sa;
	vector<int> rsa;
	vector<int> lcp;
	int k=0, n=0;
	string str;

	SuffixArray(string s){
		str = s;
		n = s.size();
		ran.resize(n+1,0);
		tmp.resize(n+1,0);
		sa.resize(n+1,0);
		rsa.resize(n+1,0);
		lcp.resize(n+1,0);
		build();
		calcLCP();
	}

	struct CompareSA {
        int n, k;
        const vector<int> &rank;
        CompareSA(int n, int k, const vector<int> &rank_sa) : n(n), k(k), rank(rank_sa) {}
        bool operator()(int i, int j) {
            if (rank[i] != rank[j]) return (rank[i] < rank[j]);
            else {
                int rank_ik = (i + k <= n ? rank[i + k] : -1);
                int rank_jk = (j + k <= n ? rank[j + k] : -1);
                return (rank_ik < rank_jk);
            }
        }
    };

	void build(){
		for(int i=0; i<=n; i++){
			sa[i] = i;
			ran[i] = i < n ? str[i] : -1;
		}
		for(k=1; k<=n; k*=2){
			CompareSA csa(n, k, ran);
			sort(sa.begin(),sa.end(),csa);
			tmp[sa[0]] = 0;
			for(int i=1; i<=n; i++){
				tmp[sa[i]] = tmp[sa[i-1]] + (csa(sa[i-1], sa[i]) ? 1 : 0);
			}
			for(int i=0; i<=n; i++){
				ran[i] = tmp[i];
			}
		}
	}

	bool contain(string t){
		int a = 0, b = str.size();
		while(b - a > 1){
			int c = (a+b) / 2;
			if(str.compare(sa[c], t.size(), t) < 0) a = c;
			else b = c;
		}
		return str.compare(sa[b], t.size(), t) == 0;
	}

	void calcLCP(){
		for(int i=0; i<=n; i++) rsa[sa[i]] = i;
		lcp[0] = 0;
		int cur = 0;
		for(int i=0; i<=n; i++){
			int pi = sa[rsa[i] - 1];
			if(cur > 0) cur--;
			for(; pi + cur < n && i + cur < n; cur++){
				if(str[pi + cur] != str[i + cur]) break;
			}
			lcp[rsa[i] - 1] = cur;
		}
	}
};

int main(){
	string s,t; cin >> s >> t;
	ll k; cin >> k;
	ll n = s.size();
	s += '#' + t;
	SuffixArray sa(s);
	ll m = s.size();
	ll T = 0;
	ll fin = -1;
	vl v(n+2,0);
	rep(i,m){
		if(sa.sa[i] > n){
			ll now = inf;
			for(ll j=i-1; j>fin; j--){
				chmin(now,sa.lcp[j]);
				if(now < k) break;
				if(sa.sa[j] < n) chmax(v[sa.sa[j]],now);
			}
			fin = i;
			now = sa.lcp[i];
			for(ll j=i+1; j<=m; j++){
				if(sa.sa[j] >= n) break;
				if(now < k) break;
				chmax(v[sa.sa[j]],now);
				chmin(now,sa.lcp[j]);
			}
		}
	}
	vl dp(n+2,0);
	rep(i,n+2){
		if(i>0) dp[i] += dp[i-1];
		if(!v[i]) continue;
		if(i>0 && !dp[i]) continue;
		dp[i+k]++;
		dp[i+v[i]+1]--;
	}
	if(dp[n]) puts("Yes");
	else puts("No");
}
accuracy: 1
time_ms: 330
memory_kb: 14812
final_rank: 6

code_snippet: #include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <stack>
#include <functional>
#include <bitset>
#include <assert.h>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(ll i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = 1<<30;
const ll linf = 1LL<<62;
const int MAX = 510000;
ll dy[8] = {0,1,0,-1,1,-1,1,-1};
ll dx[8] = {1,0,-1,0,1,-1,-1,1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){cout << a << " " << b << "\n";}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
const int mod = 1e9 + 7;
//const int mod = 998244353;


struct SuffixArray{
	vector<int> ran;
	vector<int> tmp;
	vector<int> sa;
	vector<int> rsa;
	vector<int> lcp;
	int k=0, n=0;
	string str;

	SuffixArray(string s){
		str = s;
		n = s.size();
		ran.resize(n+1,0);
		tmp.resize(n+1,0);
		sa.resize(n+1,0);
		rsa.resize(n+1,0);
		lcp.resize(n+1,0);
		build();
		calcLCP();
	}

	struct CompareSA {
        int n, k;
        const vector<int> &rank;
        CompareSA(int n, int k, const vector<int> &rank_sa) : n(n), k(k), rank(rank_sa) {}
        bool operator()(int i, int j) {
            if (rank[i] != rank[j]) return (rank[i] < rank[j]);
            else {
                int rank_ik = (i + k <= n ? rank[i + k] : -1);
                int rank_jk = (j + k <= n ? rank[j + k] : -1);
                return (rank_ik < rank_jk);
            }
        }
    };

	void build(){
		for(int i=0; i<=n; i++){
			sa[i] = i;
			ran[i] = i < n ? str[i] : -1;
		}
		for(k=1; k<=n; k*=2){
			CompareSA csa(n, k, ran);
			sort(sa.begin(),sa.end(),csa);
			tmp[sa[0]] = 0;
			for(int i=1; i<=n; i++){
				tmp[sa[i]] = tmp[sa[i-1]] + (csa(sa[i-1], sa[i]) ? 1 : 0);
			}
			for(int i=0; i<=n; i++){
				ran[i] = tmp[i];
			}
		}
	}

	bool contain(string t){
		int a = 0, b = str.size();
		while(b - a > 1){
			int c = (a+b) / 2;
			if(str.compare(sa[c], t.size(), t) < 0) a = c;
			else b = c;
		}
		return str.compare(sa[b], t.size(), t) == 0;
	}

	void calcLCP(){
		for(int i=0; i<=n; i++) rsa[sa[i]] = i;
		lcp[0] = 0;
		int cur = 0;
		for(int i=0; i<=n; i++){
			int pi = sa[rsa[i] - 1];
			if(cur > 0) cur--;
			for(; pi + cur < n && i + cur < n; cur++){
				if(str[pi + cur] != str[i + cur]) break;
			}
			lcp[rsa[i] - 1] = cur;
		}
	}
};

int main(){
	string s,t; cin >> s >> t;
	ll k; cin >> k;
	ll n = s.size();
	s += '#' + t;
	SuffixArray sa(s);
	ll m = s.size();
	ll T = 0;
	ll fin = -1;
	vl v(n+2,0);
	rep(i,m){
		if(sa.sa[i] > n){
			ll now = inf;
			for(ll j=i-1; j>fin; j--){
				chmin(now,sa.lcp[j]);
				if(now < k) break;
				if(sa.sa[j] < n) chmax(v[sa.sa[j]],now);
			}
			fin = i;
			now = sa.lcp[i];
			for(ll j=i+1; j<m; j++){
				if(sa.sa[j] >= n) break;
				if(now < k) break;
				chmax(v[sa.sa[j]],now);
				chmin(now,sa.lcp[j]);
			}
		}
	}
	vl dp(n+2,0);
	rep(i,n+2){
		if(i>0) dp[i] += dp[i-1];
		if(!v[i]) continue;
		if(i>0 && !dp[i]) continue;
		dp[i+k]++;
		dp[i+v[i]+1]--;
	}
	if(dp[n]) puts("Yes");
	else puts("No");
}
accuracy: 0.33663366336633666
time_ms: 290
memory_kb: 13932
final_rank: 17

code_snippet: #include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <stack>
#include <functional>
#include <bitset>
#include <assert.h>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(ll i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = 1<<30;
const ll linf = 1LL<<62;
const int MAX = 510000;
ll dy[8] = {0,1,0,-1,1,-1,1,-1};
ll dx[8] = {1,0,-1,0,1,-1,-1,1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){cout << a << " " << b << "\n";}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
const int mod = 1e9 + 7;
//const int mod = 998244353;


struct SuffixArray{
	vector<int> ran;
	vector<int> tmp;
	vector<int> sa;
	vector<int> rsa;
	vector<int> lcp;
	int k=0, n=0;
	string str;

	SuffixArray(string s){
		str = s;
		n = s.size();
		ran.resize(n+1,0);
		tmp.resize(n+1,0);
		sa.resize(n+1,0);
		rsa.resize(n+1,0);
		lcp.resize(n+1,0);
		build();
		calcLCP();
	}

	struct CompareSA {
        int n, k;
        const vector<int> &rank;
        CompareSA(int n, int k, const vector<int> &rank_sa) : n(n), k(k), rank(rank_sa) {}
        bool operator()(int i, int j) {
            if (rank[i] != rank[j]) return (rank[i] < rank[j]);
            else {
                int rank_ik = (i + k <= n ? rank[i + k] : -1);
                int rank_jk = (j + k <= n ? rank[j + k] : -1);
                return (rank_ik < rank_jk);
            }
        }
    };

	void build(){
		for(int i=0; i<=n; i++){
			sa[i] = i;
			ran[i] = i < n ? str[i] : -1;
		}
		for(k=1; k<=n; k*=2){
			CompareSA csa(n, k, ran);
			sort(sa.begin(),sa.end(),csa);
			tmp[sa[0]] = 0;
			for(int i=1; i<=n; i++){
				tmp[sa[i]] = tmp[sa[i-1]] + (csa(sa[i-1], sa[i]) ? 1 : 0);
			}
			for(int i=0; i<=n; i++){
				ran[i] = tmp[i];
			}
		}
	}

	bool contain(string t){
		int a = 0, b = str.size();
		while(b - a > 1){
			int c = (a+b) / 2;
			if(str.compare(sa[c], t.size(), t) < 0) a = c;
			else b = c;
		}
		return str.compare(sa[b], t.size(), t) == 0;
	}

	void calcLCP(){
		for(int i=0; i<=n; i++) rsa[sa[i]] = i;
		lcp[0] = 0;
		int cur = 0;
		for(int i=0; i<=n; i++){
			int pi = sa[rsa[i] - 1];
			if(cur > 0) cur--;
			for(; pi + cur < n && i + cur < n; cur++){
				if(str[pi + cur] != str[i + cur]) break;
			}
			lcp[rsa[i] - 1] = cur;
		}
	}
};

int main(){
	string s,t; cin >> s >> t;
	ll k; cin >> k;
	ll n = s.size();
	s += '#' + t;
	SuffixArray sa(s);
	ll m = s.size();
	ll T = 0;
	ll fin = -1;
	vl v(n+2,0);
	rep(i,m){
		if(sa.sa[i] > n){
			ll now = inf;
			for(ll j=i-1; j>fin; j--){
				chmin(now,sa.lcp[j]);
				if(now < k) break;
				if(sa.sa[j] < n) chmax(v[sa.sa[j]],now);
			}
			fin = i;
			now = sa.lcp[i];
			for(ll j=i+1; j<m; j++){
				if(sa.sa[j] >= n) break;
				if(now < k) break;
				chmax(v[sa.sa[j]],now);
				chmin(now,sa.lcp[j]);
			}
		}
	}
	vl dp(n+2,0);
	rep(i,n+2){
		if(i>0) dp[i] += dp[i-1];
		if(i>0 && (!dp[i] || !v[i])) continue;
		dp[i+k]++;
		dp[i+v[i]+1]--;
	}
	if(dp[n]) puts("Yes");
	else puts("No");
}
accuracy: 0.2871287128712871
time_ms: 290
memory_kb: 13876
final_rank: 18

code_snippet: #include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> P;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
// #define int long long
#define pb push_back
#define mp make_pair
#define eps 1e-9
#define INF 2000000000 //2e9
#define LLINF 1000000000000000ll // 1e15
#define fi first
#define sec second
#define all(x) (x).begin(),(x).end()
#define sq(x) ((x)*(x))
#define dmp(x) cerr << #x << ": " << x << endl;

template<class T> void chmin(T& a,const T& b){if(a>b)a=b;}
template<class T> void chmax(T& a,const T& b){if(a<b)a=b;}

template<class T> using MaxHeap = priority_queue<T>;
template<class T> using MinHeap = priority_queue<T,vector<T>,greater<T>>;
template<class T> vector<T> vect(int len,T elem){ return vector<T>(len,elem); }

template<class T,class U>
ostream& operator << (ostream& os,const pair<T,U>& p){
  os << p.fi << ',' << p.sec; return os;
}
template<class T,class U>
istream& operator >> (istream& is,pair<T,U>& p){
  is >> p.fi >> p.sec; return is;
}
template<class T>
ostream& operator << (ostream &os,const vector<T> &vec){
  for(int i=0;i<vec.size();i++){
    os << vec[i];
    if(i+1<vec.size())os << ' ';
  }
  return os;
}
template<class T>
istream& operator >> (istream &is,vector<T>& vec){
  for(int i=0;i<vec.size();i++)is >> vec[i];
  return is;
}
void fastio(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout<<fixed<<setprecision(20);
}

namespace Math{
  template<int MOD> // if inv is needed, this shold be prime.
  struct ModInt{
    ll val;
    ModInt():val(0ll){}
    ModInt(const ll& v):val(((v%MOD)+MOD)%MOD){}
    bool operator==(const ModInt& x)const{return val==x.val;}
    bool operator!=(const ModInt& x)const{return !(*this==x);}
    bool operator<(const ModInt& x)const{return val<x.val;}
    bool operator>(const ModInt& x)const{return val>x.val;}
    bool operator>=(const ModInt& x)const{return !(*this<x);}
    bool operator<=(const ModInt& x)const{return !(*this>x);}
    ModInt operator-()const{return ModInt(MOD-val);}
    ModInt inv()const{return this->pow(MOD-2);}
    ModInt& operator+=(const ModInt& x){if((val+=x.val)>=MOD)val-=MOD;return *this;}
    ModInt& operator-=(const ModInt& x){if((val+=MOD-x.val)>=MOD)val-=MOD;return *this;}
    ModInt& operator*=(const ModInt& x){(val*=x.val)%=MOD;return *this;}
    ModInt& operator/=(const ModInt& x){return *this *= x.inv();};
    ModInt operator+(const ModInt& x)const{return ModInt(*this)+=x;}
    ModInt operator-(const ModInt& x)const{return ModInt(*this)-=x;}
    ModInt operator*(const ModInt& x)const{return ModInt(*this)*=x;}
    ModInt operator/(const ModInt& x)const{return ModInt(*this)/=x;}
    friend istream& operator>>(istream&i,ModInt& x){ll v;i>>v;x=v;return i;}
    friend ostream& operator<<(ostream&o,const ModInt& x){o<<x.val;return o;}
    ModInt pow(ll x)const{
      auto res = ModInt(1ll);
      auto b = *this;
      while(x){
        if(x&1)res *= b;
        x >>= 1;
        b *= b;
      }
      return res;
    }
  };

  template<int MOD>
  ModInt<MOD> pow(ModInt<MOD> a,ll x){
    ModInt<MOD> res = ModInt<MOD>(1ll);
    while(x){
      if(x&1)res *= a;
      x >>= 1;
      a *= a;
    }
    return res;
  }

  constexpr int MOD = 1e9+7;
  // constexpr int MOD = 998244353;
  using mint = ModInt<MOD>;

  vector<mint> inv,fac,facinv;
  // notice: 0C0 = 1 
  ModInt<MOD> nCr(int n,int r){
    assert(!(n<r));
    assert(!(n<0||r<0));
    return fac[n]*facinv[r]*facinv[n-r];
  }
  void init(int SIZE){
    fac.resize(SIZE+1);
    inv.resize(SIZE+1);
    facinv.resize(SIZE+1);
    fac[0] = inv[1] = facinv[0] = mint(1ll);
    for(int i=1;i<=SIZE;i++)fac[i]=fac[i-1]*mint(i);
    for(int i=2;i<=SIZE;i++)inv[i]=mint(0ll)-mint(MOD/i)*inv[MOD%i];
    for(int i=1;i<=SIZE;i++)facinv[i]=facinv[i-1]*inv[i];
    return;
  }
  template<class T>
  int digit(T x){
    int res = 0;
    while(x){ x /= T(10); res++; }
    return res;
  }
  template<class T>
  int digit_sum(T x){
    int res = 0;
    while(x){ res+=x%10; x/=10; }
    return res;
  }
  template<class T>
  T gcd(T x,T y){
    if(y==T(0))return x;
    else return gcd(y,x%y);
  }
}

namespace DS{
  template<class T>
  struct RangeSum{
    vector<T> vec;
    RangeSum(){}
    RangeSum(vector<T> elems):vec(elems){
      for(int i=1;i<vec.size();i++){
        vec[i] += vec[i-1];
      }
    }
    T sum(int l,int r){
      if(l>r)return T(0);
      if(l==0)return vec[r];
      else return vec[r]-vec[l-1];
    }
  };
  template<class T>
  struct BIT{
    int N;
    vector<T> bit;
    BIT(int N):N(N){
      bit = vector<T>(N+1,T(0));
    }
    void add(int i,T x){
      i++;
      while(i<=N){ bit[i]+=x; i+=i&-i; }
      return;
    }
    T sum(int i){
      i++;
      T res = T(0);
      while(i>0){ res+=bit[i]; i-=i&-i; }
      return res;
    }
    T sum(int l,int r){// [l,r]
      assert(l<=r);
      if(l==0)return sum(r);
      else return sum(r)-sum(l-1);
    }
  };
  template<class T>
  struct SlideMin{
    vector<T> v;
    deque<int> deq;
    SlideMin(vector<T> &v):v(v){}
    void add(int id){ // add v[id]
      while(!deq.empty()&&v[deq.back()]>=v[id])deq.pop_back();
      deq.push_back(id);
    }
    T get(int id){ // [id,added]
      while(!deq.empty()&&deq.front()<id)deq.pop_front();
      assert(!deq.empty());
      return v[deq.front()];
    }
  };
  template<class T>
  struct SlideMax{
    vector<T> v;
    deque<int> deq;
    SlideMax(vector<T> &v):v(v){}
    void add(int id){
      while(!deq.empty()&&v[deq.back()]<=v[id])deq.pop_back();
      deq.push_back(id);
    }
    T get(int id){ // [id,added]
      while(!deq.empty()&&deq.front()<id)deq.pop_front();
      assert(!deq.empty());
      return v[deq.front()];
    }
  };
  template<class D,class O>
  struct LazySegmentTree{
    using DMerger = function<D(D,D)>;
    using OMerger = function<O(O,O)>;
    using Applier = function<D(D,O,int)>;

    int length;

    D d_unit;
    O o_unit;

    vector<D> seg;
    vector<O> lazy;

    DMerger dm;
    OMerger om;
    Applier app;

    void lazy_evaluate(int k,int len){
      if(lazy[k] == o_unit) return;
      if(len>1){
        lazy[2*k+1] = om(lazy[2*k+1],lazy[k]);
        lazy[2*k+2] = om(lazy[2*k+2],lazy[k]);
      }
      seg[k] = app(seg[k],lazy[k],len);
      lazy[k] = o_unit;
    }
    void update(int a,int b,int k,int l,int r,O x){
      lazy_evaluate(k,r-l);
      if(r<=a||b<=l)return;
      else if(a<=l&&r<=b){
        lazy[k] = om(lazy[k],x);
        lazy_evaluate(k,r-l);
      }else{
        update(a,b,k*2+1,l,(l+r)/2,x);
        update(a,b,k*2+2,(l+r)/2,r,x);
        seg[k] = dm(seg[k*2+1],seg[k*2+2]);
      }
    }
    void update(int a,int b,O x){
      update(a,b,0,0,length,x);
    }
    D query(int a,int b,int k,int l,int r){
      lazy_evaluate(k,r-l);
      if(r<=a||b<=l)return d_unit; 
      else if(a<=l&&r<=b)return seg[k];
      else{
        D lch = query(a,b,k*2+1,l,(l+r)/2);
        D rch = query(a,b,k*2+2,(l+r)/2,r);
        return dm(lch,rch);
      }
    }
    D query(int a,int b){
      return query(a,b,0,0,length);
    }
    LazySegmentTree(int n,D d_unit,O o_unit,DMerger dm,OMerger om,Applier app)
      :length(1),d_unit(d_unit),o_unit(o_unit),dm(dm),om(om),app(app) {
      while(length<n){ length <<= 1; }
      seg.assign(length * 2, d_unit);
      lazy.assign(length * 2, o_unit);
    }
    LazySegmentTree(vector<D> vec,D d_unit,O o_unit,DMerger dm,OMerger om,Applier app)
      :length(1),d_unit(d_unit),o_unit(o_unit),dm(dm),om(om),app(app) {
      while(length<vec.size()){ length <<= 1; }
      seg.assign(length * 2, d_unit);
      lazy.assign(length * 2, o_unit);
      for(int i=0;i<vec.size();i++)seg[length-1+i] = vec[i];
      for(int i=length-2;i>=0;i--)seg[i] = dm(seg[i*2+1],seg[i*2+2]);
    }
  };
  // RangeAddRangeSum update : a[l,r) += c
  // verified https://atcoder.jp/contests/abc153/submissions/9866001
  template<class T>
  LazySegmentTree<T,T> RangeAddRangeSum(int size){
    auto dm = [](T a,T b){return a+b;};
    auto om = [](T a,T b){return a+b;};
    auto app = [](T dat,T lz,int len){return dat+lz*T(len);};
    return LazySegmentTree<T,T>(size,T(0),T(0),dm,om,app);
  }
  template<class T>
  LazySegmentTree<T,T> RangeAddRangeSum(vector<T> vec){
    auto dm = [](T a,T b){return a+b;};
    auto om = [](T a,T b){return a+b;};
    auto app = [](T dat,T lz,int len){return dat+lz*T(len);};
    return LazySegmentTree<T,T>(vec,T(0),T(0),dm,om,app);
  }
  // RangeAddRangeMin
  // NOT verified yet
  template<class T>
  LazySegmentTree<T,T> RangeAddRangeMin(int size){
    auto dm = [](T a,T b){return min(a,b);};
    auto om = [](T a,T b){return a+b;};
    auto app = [](T dat,T lz,int len){return dat+lz;};
    return LazySegmentTree<T,T>(size,T(INF),T(0),dm,om,app);
  }
  template<class T>
  LazySegmentTree<T,T> RangeAddRangeMin(vector<T> vec){
    auto dm = [](T a,T b){return min(a,b);};
    auto om = [](T a,T b){return a+b;};
    auto app = [](T dat,T lz,int len){return dat+lz;};
    return LazySegmentTree<T,T>(vec,T(INF),T(0),dm,om,app);
  }
  // RangeAffineRangeSum update (l,r,(p,q)) : a[i] = p * a[i] + q { i in [l,r) }
  // verified https://judge.yosupo.jp/submission/3354
  template<class T>
  LazySegmentTree<ll,pair<T,T>> RangeAffineRangeSum(int size){
    using f = pair<T,T>;
    auto dm = [](T a,T b){return a+b;};
    auto om = [](f a,f b){return f(b.fi*a.fi,b.fi*a.sec+b.sec);};
    auto app = [](T dat,f lz,int len){return lz.fi*dat+lz.sec*T(len);};
    return LazySegmentTree<T,f>(size,T(0),f(T(1),T(0)),dm,om,app);
  }
  template<class T>
  LazySegmentTree<T,pair<T,T>> RangeAffineRangeSum(vector<T> vec){
    using f = pair<T,T>;
    auto dm = [](T a,T b){return a+b;};
    auto om = [](f a,f b){return f(b.fi*a.fi,b.fi*a.sec+b.sec);};
    auto app = [](T dat,f lz,int len){return lz.fi*dat+lz.sec*T(len);};
    return LazySegmentTree<T,f>(vec,T(0),f(T(1),T(0)),dm,om,app);
  }
}

namespace Util{
  template<class T>
  vector<pair<T,int>> runLength(vector<T> v){
    vector<pair<T,int>> res;
    for(int i=0;i<v.size();i++){
      if(res.empty()||res.back().first!=v[i])res.push_back(make_pair(v[i],1));
      else res.back().second++;
    }
    return res;
  }
  template<class T>
  void compress(vector<T> &v){
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
  }
}

template<class Cost = int>
struct edge{
  int from,to;
  Cost cost;
  edge(){}
  edge(int f,int t,Cost cost):from(f),to(t),cost(cost){}
};

struct SuffixArray{
  string s;
  vector<int> sa;
  vector<int> rank;
  vector<int> lcp;
  explicit SuffixArray(string s):s(s){
    int n = s.size();
    sa.resize(n+1);
    rank.resize(n+1);
    vector<int> tmp(n+1);
    for(int i=0;i<=n;i++){
      rank[i] = (i<n)?s[i]:-1;
      sa[i] = i;
    }
    for(int k=1;k<=n;k*=2){
      auto compare_sa = 
        [&](const int &i,const int &j){
           if(rank[i]!=rank[j])return rank[i]<rank[j];
           else{
             int ri=(i+k<=s.size())?rank[i+k]:-1;
             int rj=(j+k<=s.size())?rank[j+k]:-1;
             return ri<rj;
           }
        };
      sort(sa.begin(),sa.end(),compare_sa);
      tmp[sa[0]]=0;
      for(int i=1;i<=n;i++)tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i])?1:0);
      for(int i=0;i<=n;i++)rank[i]=tmp[i];
    }
  }
  size_t size() const {
    return s.size();
  }
  int operator [] (int id) const {
    return sa[id];
  }
  bool contain(string t){
    int l = 0,r = s.size()+1;
    while(r-l>1){
      int mid = (l+r)/2;
      if(s.compare(sa[mid],t.size(),t)<0){
        l = mid;
      }else{
        r = mid;
      }
    }
    return s.compare(sa[r],t.size(),t)==0;
  }
};

struct LongestCommonPrefix{
  const SuffixArray &sa;
  vector<int> lcp,rank;
  explicit LongestCommonPrefix(const SuffixArray &sa):sa(sa){
    int n = sa.size();
    lcp.resize(sa.size()+1);
    rank.resize(sa.size()+1);
    for(int i=0;i<=sa.size();i++){
      rank[sa[i]]=i;
    }
    int h = 0;
    lcp[0] = 0;
    for(int i=0;i<sa.size();i++){
      int j = sa[rank[i]-1];
      if(h>0)h--;
      for(;i+h<n&&j+h<n;h++)if(sa.s[i+h]!=sa.s[j+h])break;
      lcp[rank[i]-1] = h;
    }
  }
  int operator [] (int id) const {
    assert(id>=0&&id<lcp.size());
    return lcp[id];
  }
};
 
signed main(){
  fastio();
  string s,t;
  int k;
  cin >> s;
  cin >> t;
  cin >> k;
  string S = s + "$" + t;
  SuffixArray sa(S);
  LongestCommonPrefix lcp(sa);
  auto seg = DS::RangeAddRangeSum<int>(s.size()+1);
  auto lcpseg = DS::RangeAddRangeMin(lcp.lcp);
  set<int> Tidx;
  vector<int> rev(s.size());
  for(int i=0;i<=S.size();i++){
    if(sa[i]>s.size())Tidx.insert(i);
    if(sa[i]<s.size())rev[sa[i]] = i;
  }
  seg.update(0,1,1);
  for(int i=0;i<s.size();i++){
    if(seg.query(i,i+1)==0)continue;
    int sidx = rev[i];
    auto it = Tidx.lower_bound(sidx);
    int lap = 0;
    if(it!=Tidx.end()){
      chmax(lap,lcpseg.query(sidx,*it));
    }
    if(it!=Tidx.begin()){
      it--;
      chmax(lap,lcpseg.query(*it,sidx));
    }
    if(lap<k)continue;
    seg.update(i+k,i+lap+1,1);
  }
  if(seg.query(s.size(),s.size()+1)==0)cout << "No" << endl;
  else cout << "Yes" << endl;
  return 0;
}
accuracy: 1
time_ms: 600
memory_kb: 32000
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

struct SuffixArray{
  string s;
  vector<int> sa,rev;

  SuffixArray(){}
  SuffixArray(const string &S):s(S){
    int n=s.size();
    s.push_back('$');
    sa.resize(n+1);
    iota(sa.begin(),sa.end(),0);
    sort(sa.begin(),sa.end(),
         [&](int a,int b){
           if(s[a]==s[b]) return a>b;
           return s[a]<s[b];
         });
    vector<int> c(n+1,0),r(n+1),cnt(n+1);
    for(int i=0;i<=n;i++) r[i]=s[i];
    for(int len=1;len<=n;len*=2){
      for(int i=0;i<=n;i++){
        c[sa[i]]=i;
        if(i>0 &&
           r[sa[i-1]]==r[sa[i]] &&
           sa[i-1]+len<=n &&
           r[sa[i-1]+len/2]==r[sa[i]+len/2]) c[sa[i]]=c[sa[i-1]];
      }
      iota(cnt.begin(),cnt.end(),0);
      copy(sa.begin(),sa.end(),r.begin());
      for(int i=0;i<=n;i++){
        int s1=r[i]-len;
        if(s1>=0) sa[cnt[c[s1]]++]=s1;
      }
      c.swap(r);
    }
    rev.resize(n+1);
    for(int i=0;i<=n;i++) rev[sa[i]]=i;
  }
  int operator[](int i) const{return sa[i];}

  bool lt_substr(string &t,int si,int ti){
    int sn=s.size(),tn=t.size();
    while(si<sn&&ti<tn){
      if(s[si]<t[ti]) return 1;
      if(s[si]>t[ti]) return 0;
      si++;ti++;
    }
    return si==sn&&ti<tn;
  }

  int lower_bound(string& t){
    int l=0,r=s.size();
    while(l+1<r){
      int m=(l+r)>>1;
      if(lt_substr(t,sa[m],0)) l=m;
      else r=m;
    }
    return r;
  }

  int upper_bound(string& t){
    t.back()++;
    int res=lower_bound(t);
    t.back()--;
    return res;
  }

  // O(|T|*log|S|)
  int count(string& T){
    return upper_bound(T)-lower_bound(T);
  }
};


struct LongestCommonPrefix{
  SuffixArray sa;

  vector<int> ht;
  vector< vector<int> > dat;
  LongestCommonPrefix(string &s):sa(s){
    int n=s.size();
    vector<int> lcp(n,0);

    int t=0;
    lcp[0]=0;
    for(int i=0;i<n;i++){
      int j=sa[sa.rev[i]-1];
      if(t>0) t--;
      for(;j+t<n&&i+t<n;t++){
        if(sa.s[j+t]!=sa.s[i+t]) break;
      }
      lcp[sa.rev[i]-1]=t;
    }

    int h=1;
    while((1<<h)<n) h++;
    dat.assign(h,vector<int>(n));
    ht.assign(n+1,0);
    for(int j=2;j<=n;j++) ht[j]=ht[j>>1]+1;

    for(int j=0;j<n;j++) dat[0][j]=lcp[j];
    for(int i=1,p=1;i<h;i++,p<<=1)
      for(int j=0;j<n;j++)
        dat[i][j]=min(dat[i-1][j],dat[i-1][min(j+p,n-1)]);
  }

  // a, b are indices for suffix array
  int query(int a,int b){
    assert(a!=b);
    if(a>b) swap(a,b);
    int l=b-a;
    return min(dat[ht[l]][a],dat[ht[l]][b-(1<<ht[l])]);
  }

  // a, b are indices for string
  int lcp(int a,int b){
    return query(sa.rev[a],sa.rev[b]);
  }
};


template <typename E>
struct SegmentTree{
  using H = function<E(E,E)>;
  int n,height;
  H h;
  E ei;
  vector<E> laz;
  SegmentTree(H h,E ei):h(h),ei(ei){}
  void init(int n_){
    n=1;height=0;
    while(n<n_) n<<=1,height++;
    laz.assign(2*n,ei);
  }
  inline void eval(int k){
    if(laz[k]==ei) return;
    laz[(k<<1)|0]=h(laz[(k<<1)|0],laz[k]);
    laz[(k<<1)|1]=h(laz[(k<<1)|1],laz[k]);
    laz[k]=ei;
  }
  inline void thrust(int k){
    for(int i=height;i;i--) eval(k>>i);
  }
  void update(int a,int b,E x){
    thrust(a+=n);
    thrust(b+=n-1);
    for(int l=a,r=b+1;l<r;l>>=1,r>>=1){
      if(l&1) laz[l]=h(laz[l],x),l++;
      if(r&1) --r,laz[r]=h(laz[r],x);
    }
  }
  E get_val(int a){
    thrust(a+=n);
    return laz[a];
  }
  void set_val(int a,E x){
    thrust(a+=n);
    laz[a]=x;
  }
};

//INSERT ABOVE HERE
signed main(){
  string s,t;
  cin>>s>>t;

  string b=s+'%'+t;
  LongestCommonPrefix lcp(b);

  int n=s.size(),m=t.size();

  set<int> ss;
  for(int i=0;i<=n+1+m;i++){
    if(!isalpha(b[lcp.sa[i]])) continue;
    if(n<lcp.sa[i]) ss.emplace(i);
  }

  vector<int> nx(n+1,-1);
  for(int i=0;i<=n+1+m;i++){
    if(!isalpha(b[lcp.sa[i]])) continue;
    int k=lcp.sa[i];
    if(k>=n) continue;

    auto it=ss.upper_bound(i);
    if(it!=ss.end()) chmax(nx[k],lcp.query(i,*it));
    if(it!=ss.begin()) it--;
    if(it!=ss.end()) chmax(nx[k],lcp.query(i,*it));
  }

  int len;
  cin>>len;

  auto h=[&](int a,int b){return a||b;};
  int ei=0;
  SegmentTree<int> seg(h,ei);
  seg.init(n+m+1000);

  seg.set_val(0,1);
  for(int i=0;i<n;i++){
    if(!seg.get_val(i)) continue;
    if(nx[i]<len) continue;
    int nl=i+len;
    int nr=i+nx[i]+1;
    seg.update(nl,nr,1);
  }

  cout<<(seg.get_val(n)?"Yes":"No")<<endl;
  return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 52160
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;

typedef long long ll;
constexpr int INF = 1<<30;

struct SuffixArray{
    int n, k;
    string s;
    vector<int> rank, tmp, sa;

    function<bool(const int&, const int&)> comp = [&](const int &i, const int &j){
        if(rank[i] != rank[j]) return rank[i] < rank[j];
        else{
            int ri = i+k <= n ? rank[i+k] : -1;
            int rj = j+k <= n ? rank[j+k] : -1;
            return ri < rj;
        }
    };
    void construct(const string &str){
        s = str;
        n = s.size();
        rank.resize(n+1);
        tmp.resize(n+1);
        sa.resize(n+1);

        for(int i=0;i<=n;i++){
            sa[i] = i;
            rank[i] = i < n ? s[i] : -1;
        }

        for(k = 1; k<=n; k<<=1){
            sort(sa.begin(), sa.begin()+n+1, comp);
            tmp[sa[0]] = 0;
            for(int i=1;i<=n;i++){
                tmp[sa[i]] = tmp[sa[i-1]] + (comp(sa[i-1],sa[i]) ? 1 : 0);
            }
            for(int i=0;i<=n;i++){
                rank[i] = tmp[i];
            }
        }
    }
    bool contain(const string &t){
        int a = 0, b = n;
        while(b-a > 1){
            int c = (a+b)/2;
            if(s.compare(sa[c], t.size(), t) < 0){
                a = c;
            }else{
                b = c;
            }
        }
        return s.compare(sa[b], t.size(), t) == 0;
    }

    int operator[] (int i) const {
        return sa[i];
    }
};

struct LCP{
    int n;
    vector<int> rank;
    vector<int> lcp;
    SuffixArray sa;

    void construct(const string &str){
        int n = str.size();
        sa.construct(str);
        rank.resize(n+1);
        lcp.resize(n);
        for(int i=0;i<=n;i++) rank[sa[i]] = i;

        int h = 0;
        for(int i=0;i<n;i++){
            int j = sa[rank[i]-1];
            if(h>0) h--;
            for(; j+h < n && i+h < n; h++){
                if(str[j+h] != str[i+h]) break;
            }
            lcp[rank[i]-1] = h;
        }
    }

    int operator[] (int i) const {
        return lcp[i];
    }
};

template <typename Monoid>
struct SegmentTree{
private:
    using F = function<Monoid(Monoid, Monoid)>;
    int N;
    vector<Monoid> node;
    F f;
    Monoid e;  // identity element

public:
    SegmentTree(){}
    SegmentTree(F f, Monoid e):f(f), e(e){}
    void init(int sz){
        N = 1;
        while(N < sz) N <<= 1;
        node.assign(2*N-1, e);
    }
    void build(vector<Monoid>& v){
        int sz = int(v.size());
        init(sz);
        for(int i=0; i<sz; i++){
            node[i+N-1] = v[i];
        }
        for(int i=N-2; i>=0; i--){
            node[i] = f(node[i*2+1], node[i*2+2]);
        }
    }
    void update(int k, Monoid x){
        k += N-1;
        node[k] = x;
        while(k > 0){
            k = (k-1)/2;
            node[k] = f(node[2*k+1], node[2*k+2]);
        }
    }
    // [a,b)
    Monoid query(int a, int b){return query(a, b, 0, 0, N);}
    Monoid query(int a, int b, int k, int l, int r){
        if(b <= l || r <= a) return e;
        if(a <= l && r <= b) return node[k];
        Monoid vl, vr;
        vl = query(a, b, 2*k+1, l, (l+r)/2);
        vr = query(a, b, 2*k+2, (l+r)/2, r);
        return f(vl, vr);
    }
};

int main(){
    int n, k;
    string s, t;
    cin >> s >> t >> k;
    n = s.size();
    s += '#' + t;
    LCP lcp;
    SuffixArray sa;
    lcp.construct(s);
    sa = lcp.sa;
    vector<int> dp(n+2), tpos;
    for(int i=0;i<=s.size();i++){
        if(sa[i] > n) tpos.push_back(i);
    }
    auto f = [&](int a, int b){return min(a,b);};
    SegmentTree<int> seg(f, INF);
    seg.build(lcp.lcp);
    dp[0] = 1;
    dp[1] = -1;
    for(int i=0;i<n;i++){
        int j = lcp.rank[i], maxi = 0;
        auto itr = lower_bound(tpos.begin(), tpos.end(), j);
        if(itr != tpos.begin()){
            auto tmp = itr;
            maxi = max(maxi, seg.query(*--tmp, j));
        }
        if(itr != tpos.end()){
            auto tmp = itr;
            maxi = max(maxi, seg.query(j, *tmp));
        }
        if(maxi >= k && dp[i] > 0){
            dp[i+k]++;
            dp[i+maxi+1]--;
        }
        dp[i+1] += dp[i];
    }
    cout << (dp[n] > 0 ? "Yes" : "No") << endl;
    return 0;
}
accuracy: 1
time_ms: 700
memory_kb: 22436
final_rank: 14

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005

int A_length,B_length,T_length,range;
int Rank[2*SIZE]; //接尾辞文字列の開始位置iの、辞書順にsortした際の順位表
int Suffix_Array[2*SIZE]; //接尾辞文字列の開始位置<インデックス>→毎回、辞書順に開始位置をソートする
int Work[2*SIZE];
int LCP[2*SIZE],LCP_Rank[2*SIZE];
int max_cover_length[SIZE];
int dp[SIZE];
char A[SIZE],B[SIZE],T[2*SIZE];

//まずrank[a]とrank[b]を比較、等しければrank[a+range],rank[b+range]を比較
bool compare_Suffix_Array(int a,int b){
	if(Rank[a] != Rank[b])return Rank[a] < Rank[b];
	else{
		int rank_a = a + range <= T_length ? Rank[a+range]:-1; //rangeを足した部分が範囲外なら、最高にするため、rankを-1にする
		int rank_b = b + range <= T_length ? Rank[b+range]:-1;
		return rank_a < rank_b;
	}
}

//文字列Tの接尾辞配列を構築
void make_Suffix_Array(){
	for(int i = 0; i <= T_length; i++){
		Suffix_Array[i] = i;
		Rank[i] = i < T_length? T[i]:-1; //初期ランクは文字コードにする。T[T_length]は空文字なので、最高となるように-1とする
	}

	//range,2*range,4*range,とソート幅を次第に伸ばしていく
	for(range = 1; range <= T_length; range*=2){
		sort(Suffix_Array,Suffix_Array+(T_length+1),compare_Suffix_Array); //range文字の幅でsuffix_Arrayをソート

		Work[Suffix_Array[0]] = 0;
		for(int i = 1; i <= T_length; i++){
			Work[Suffix_Array[i]] = Work[Suffix_Array[i-1]] + (compare_Suffix_Array(Suffix_Array[i-1],Suffix_Array[i])?1:0);
		}
		for(int i = 0; i <= T_length; i++){
			Rank[i] = Work[i];
		}
	}
}

void construct_LCP(){

	int n = T_length;
	for(int i = 0; i <= n; i++)LCP_Rank[Suffix_Array[i]] = i; //位置Suffix_Array[i]の配列上の位置を格納

	int h = 0;
	LCP[0] = 0;

	for(int i = 0; i < n; i++){
		//文字列中での位置iの接尾辞と、接尾辞配列中でその1つ前の接尾辞のLCPを求める
		int j = Suffix_Array[LCP_Rank[i]-1]; //LCP_Rank[n] == 0なので、マイナスになる心配はない

		//hを先頭の分1減らし、後ろが一致しているだけ増やす
		if(h > 0)h--;
		for(; j+h < n && i+h < n; h++){

			if(T[j+h] != T[i+h])break;
		}
		LCP[LCP_Rank[i]-1] = h;
	}
}


int main(){


	scanf("%s",A);
	for(A_length = 0; A[A_length] != '\0'; A_length++){

		T[A_length] = A[A_length];
	}
	T[A_length] = '@';
	T_length = A_length+1;

	scanf("%s",B);
	for(B_length = 0; B[B_length] != '\0'; B_length++,T_length++){

		T[T_length] = B[B_length];
	}

	int LEN;
	scanf("%d",&LEN);

	make_Suffix_Array();
	construct_LCP();

	int cover_length = 0;

	for(int i = 0; i <= T_length; i++){

		if(Suffix_Array[i] < A_length){

			max_cover_length[Suffix_Array[i]] = max(max_cover_length[Suffix_Array[i]],cover_length);
			cover_length = min(cover_length,LCP[i]);

		}else{

			cover_length = LCP[i];
		}
	}

	cover_length = 0;
	for(int i = T_length; i >= 1; i--){
		if(Suffix_Array[i] < A_length){

			max_cover_length[Suffix_Array[i]] = max(max_cover_length[Suffix_Array[i]],cover_length);
			cover_length = min(cover_length,LCP[i-1]);

		}else{

			cover_length = LCP[i-1];
		}
	}

	for(int i = 0; i <= A_length+1; i++){

		dp[i] = 0;
	}

	dp[0] = 1;
	dp[1] = -1;

	for(int i = 0; i <= A_length; i++){

		if(i > 0)dp[i] += dp[i-1];
		if(dp[i] == 0 || max_cover_length[i] < LEN || i == A_length)continue;

		dp[i+LEN]++;
		int right = min(A_length+1,i+max_cover_length[i]+1);
		dp[right]--;
	}

	if(dp[A_length] > 0){

		printf("Yes\n");
	}else{

		printf("No\n");
	}

	return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 13268
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct Suffix_Array {
  string str;
  int strlen, nowlen;
  vector<long long> rank, tmp, sa, lcp;
  Suffix_Array(string news = "", bool reqlcp = 0) {
    str = news;
    strlen = str.size();
    nowlen = 0;
    rank.resize(strlen + 1);
    tmp.resize(strlen + 1);
    sa.resize(strlen + 1);
    constuct_sa();
    if(reqlcp) constuct_lcp();
  }

  void constuct_sa() {
    auto cmp = [&](int l, int r) {
      if(rank[l] != rank[r]) return rank[l] < rank[r];
      int rx = l + nowlen <= strlen ? rank[l + nowlen] : -1;
      int ly = r + nowlen <= strlen ? rank[r + nowlen] : -1;
      return rx < ly;
    };

    for(int i = 0; i <= strlen; ++i) {
      sa[i] = i;
      rank[i] = i < strlen ? str[i] : -1;
    }
    for(nowlen = 1; nowlen <= strlen; nowlen *= 2) {
      sort(sa.begin(), sa.end(), cmp);
      tmp[sa[0]] = 0;
      for(int i = 1; i <= strlen; ++i)
        tmp[sa[i]] = tmp[sa[i - 1]] +
                     (cmp(sa[i - 1], sa[i]) ? 1 : 0);
      for(int i = 0; i <= strlen; ++i) rank[i] = tmp[i];
    }
  }
  // Longest Common Prefix Array
  void constuct_lcp() {
    lcp.resize(strlen + 1);
    for(int i = 0; i <= strlen; ++i) rank[sa[i]] = i;
    int h = 0;
    lcp[0] = 0;
    for(int i = 0; i < strlen; ++i) {
      int j = sa[rank[i] - 1];
      if(h > 0) --h;
      for(; j + h < strlen && i + h < strlen; ++h)
        if(str[j + h] != str[i + h]) break;
      lcp[rank[i] - 1] = h;
    }
  }

  bool contain(string &nowt) {
    int lef = 0, righ = strlen, tsize = nowt.size();
    while(righ - lef > 1) {
      int mid = (lef + righ) / 2;
      if(str.compare(sa[mid], tsize, nowt) < 0)
        lef = mid;
      else
        righ = mid;
    }
    return str.compare(sa[righ], tsize, nowt) == 0;
  }
};

string s, t, st;
long long k;
Suffix_Array suf;
vector<long long> dp, memo;

bool solve();

int main() {
  cin >> s >> t >> k;
  if(solve())
    cout << "Yes" << endl;
  else
    cout << "No" << endl;
  return 0;
}

bool solve() {
  long long ssize = s.size(), stsize;
  st = s + "#" + t;
  stsize = st.size();
  suf = Suffix_Array(st, 1);
  memo.assign(s.size(), 0);
  long long now = 0;
  for(int i = 0; i <= stsize; ++i) {
    if(suf.sa[i] < ssize) {
      memo[suf.sa[i]] = max(memo[suf.sa[i]], now);
      now = min(now, suf.lcp[i]);
    }
    else
      now = suf.lcp[i];
  }
  now = 0;
  for(int i = stsize; i >= 1; --i) {
    if(suf.sa[i] < ssize) {
      memo[suf.sa[i]] = max(memo[suf.sa[i]], now);
      now = min(now, suf.lcp[i - 1]);
    }
    else
      now = suf.lcp[i - 1];
  }
  dp.assign(s.size() + 2, 0);
  dp[0] = 1;
  dp[1] = -1;
  for(int i = 0; i <= ssize; ++i) {
    if(i != 0) dp[i] += dp[i - 1];
    if(i == ssize || memo[i] < k || dp[i] == 0) continue;
    ++dp[i + k];
    --dp[min(i + memo[i] + 1, ssize + 1)];
  }
  return dp[ssize] > 0;
}
accuracy: 1
time_ms: 380
memory_kb: 19432
final_rank: 9

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>

#include <iostream>
#include <complex>
#include <string>
#include <algorithm>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

#include <functional>
#include <cassert>

typedef long long ll;
using namespace std;

#ifndef LOCAL
#define debug(x) ;
#else
#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;

template <typename T1, typename T2>
ostream &operator<<(ostream &out, const pair<T1, T2> &p) {
  out << "{" << p.first << ", " << p.second << "}";
  return out;
}

template <typename T>
ostream &operator<<(ostream &out, const vector<T> &v) {
  out << '{';
  for (const T &item : v) out << item << ", ";
  out << "\b\b}";
  return out;
}
#endif

#define mod 1000000007 //1e9+7(prime number)
#define INF 1000000000 //1e9
#define LLINF 2000000000000000000LL //2e18
#define SIZE 200010

/* SuffixArray (Source: 蟻本) */

//O(N log^2 N)
//pos[i] := 接頭辞の開始位置
//lcp[i] := lcp(s[pos[i]:n-1], s[pos[i-1]:n-1])
struct SuffixArray{
  vector<int> pos, lcp;

  SuffixArray(const char *S){
    int n = strlen(S), k;
    vector<int> rank(S, S+n), tmp(n);
    auto comp = [&](const int &i, const int &j){
                  if (rank[i] != rank[j]) return rank[i] < rank[j];
                  return (i+k < n ? rank[i+k] : -1) < (j+k < n ? rank[j+k] : -1);
                };

    pos.resize(n);
    iota(pos.begin(), pos.end(), 0);

    for(k=1;k<n;k*=2){
      sort(pos.begin(), pos.end(), comp);
      tmp[pos[0]] = 0;
      for(int i=1;i<n;i++)
        tmp[pos[i]] = tmp[pos[i-1]] + comp(pos[i-1], pos[i]);
      for(int i=0;i<n;i++)
        rank[i] = tmp[i];
    }

    //LongestCommonPrefixArray
    lcp.resize(n);
    for(int i=0;i<n;i++) rank[pos[i]] = i;

    for(int i=0, h=0; i<n; i++) {
      if(rank[i] + 1 < n) {
        for(int j = pos[rank[i] + 1]; max(i, j) + h < n && S[i + h] == S[j + h]; h++);
        lcp[rank[i] + 1] = h;
        if(h > 0) h--;
      }
    }
  }

  int operator[](int k) const {
    return pos[k];
  }
};

/* SimpleSegTree(0-index) */

template <typename Type = int>
struct SimpleSegTree{
  int segn2;
  Type initVal;
  vector<Type> data;
  function<Type(Type, Type)> merge;

  SimpleSegTree(int n, Type initVal, function<Type(Type, Type)> merge):
    initVal(initVal), merge(merge)
  {
    for(segn2=1; segn2<n; segn2*=2);
    data.assign(segn2*2, initVal);
  }

  SimpleSegTree(int n): //RangeMinimunQuery
    SimpleSegTree(n, INF, [](Type a, Type b){ return min(a, b); }) {}

  SimpleSegTree(int n, Type initVal): //RangeMinimunQuery
    SimpleSegTree(n, initVal, [](Type a, Type b){ return min(a, b); }) {}

  //get value [a,b)
  Type query(int a, int b, int l = 0, int r = -1, int k = 0){
    if(r == -1) r = segn2;
    if(a <= l && r <= b) return data[k];
    if(r <= a || b <= l) return initVal;
    return merge(query(a,b,l,(l+r)/2,k*2+1),query(a,b,(l+r)/2,r,k*2+2));
  }

  //set kth number x
  void set(int k, Type x){
    k += segn2-1;
    data[k] = x;
    while(k > 0){
      k = (k-1)/2;
      data[k] = merge(data[k*2+1], data[k*2+2]);
    }
  }
};

int dic[SIZE];

int dp[SIZE];

int main(){
  char ST[SIZE * 2];
  int N, M, K;



  scanf("%s", ST);
  N = strlen(ST);
  ST[N] = '#';
  scanf("%s", ST+N+1);
  M = strlen(ST) - N - 1;

  scanf("%d", &K);

  SuffixArray sa(ST);
  SimpleSegTree<int> seg(N+M+1);

  debug(N+M+1);

  set<int> ss;

  for(int i=0; i<N+M+1; i++) {
    if(sa.pos[i] > N) {
      ss.insert(i);
      //ss[i] = sa.pos[i];
    } else {
      dic[sa.pos[i]] = i;
    }
    seg.set(i, sa.lcp[i]);
    debug(sa.lcp[i]);
  }


  dp[0] = 1;
  dp[1] = -1;

  for(int i=0; i<N; i++) {
    auto it = ss.lower_bound(dic[i]);

    if(dp[i] == 0) continue;

    int l, r;

    int maxLen = 0;

    if(it != ss.end()) {
      r = *it;
      maxLen = max(maxLen, seg.query(dic[i]+1, r+1));
    }

    if(it != ss.begin()) {
      it--;
      l = *it;
      maxLen = max(maxLen, seg.query(l+1, dic[i]+1));
    }

    if (maxLen >= K) {
      dp[i+K] += 1;
      dp[i+maxLen+1] -= 1;
    }


    dp[i+1] += dp[i];
    debug(dp[i]);

    debug(ST+i);
    debug(maxLen);
  }

  if(dp[N]) {
    cout << "Yes" << endl;
  } else {
    cout << "No" << endl;
  }


  return 0;
}
accuracy: 1
time_ms: 500
memory_kb: 20884
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#define whlie while
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define rep(i,N) for(int i = 0; i < (N); i++)
#define repr(i,N) for(int i = (N) - 1; i >= 0; i--)
#define rep1(i,N) for(int i = 1; i <= (N) ; i++)
#define repr1(i,N) for(int i = (N) ; i > 0 ; i--)
#define each(x,v) for(auto& x : v)
#define all(v) (v).begin(),(v).end()
#define sz(v) ((int)(v).size())
#define vrep(v,it) for(auto it = v.begin(); it != v.end(); it++)
#define vrepr(v,it) for(auto it = v.rbegin(); it != v.rend(); it++)
#define ini(...) int __VA_ARGS__; in(__VA_ARGS__)
#define inl(...) ll __VA_ARGS__; in(__VA_ARGS__)
#define ins(...) string __VA_ARGS__; in(__VA_ARGS__)
using namespace std; void solve();
using ll = long long; using vl = vector<ll>;
using vi = vector<int>; using vvi = vector< vector<int> >;
constexpr int inf = 1001001001;
constexpr ll infLL = (1LL << 61) - 1;
struct IoSetupNya {IoSetupNya() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); cerr << fixed << setprecision(7);} } iosetupnya;
template<typename T, typename U> inline bool amin(T &x, U y) { return (y < x) ? (x = y, true) : false; }
template<typename T, typename U> inline bool amax(T &x, U y) { return (x < y) ? (x = y, true) : false; }
template<typename T, typename U> ostream& operator <<(ostream& os, const pair<T, U> &p) { os << p.first << " " << p.second; return os; }
template<typename T, typename U> istream& operator >>(istream& is, pair<T, U> &p) { is >> p.first >> p.second; return is; }
template<typename T> ostream& operator <<(ostream& os, const vector<T> &v) { int s = (int)v.size(); rep(i,s) os << (i ? " " : "") << v[i]; return os; }
template<typename T> istream& operator >>(istream& is, vector<T> &v) { for(auto &x : v) is >> x; return is; }
void in(){} template <typename T,class... U> void in(T &t,U &...u){ cin >> t; in(u...);}
void out(){cout << "\n";} template <typename T,class... U> void out(const T &t,const U &...u){ cout << t; if(sizeof...(u)) cout << " "; out(u...);}
template<typename T>void die(T x){out(x); exit(0);}
#ifdef NyaanDebug
  #include "NyaanDebug.h"
  #define trc(...) do { cerr << #__VA_ARGS__ << " = "; dbg_out(__VA_ARGS__);} while(0)
  #define trca(v,...) do { cerr << #v << " = "; array_out(v , __VA_ARGS__ );} while(0)
#else
  #define trc(...)
  #define trca(...)
  int main(){solve();}
#endif

constexpr int MOD = /** 1000000007; //*/ 998244353;
/////////////////

// Suffix Array
//verify https://judge.yosupo.jp/submission/240
struct SuffixArray{
  int _size;
  vector<int> sa;
  string &s;
  SuffixArray(string &str):_size(str.size()) , s(str) {
    // うしさんのO( N logN )の実装
    s.push_back(0);
    sa.resize(s.size());
    iota(begin(sa), end(sa), 0);
    sort(begin(sa), end(sa), [&](int a, int b) {
      return s[a] == s[b] ? a > b : s[a] < s[b];
    });
    vector< int > classes(s.size()), c(s.begin(), s.end()), cnt(s.size());
    for(int len = 1; len < (int)s.size(); len <<= 1) {
      for(int i = 0; i < (int)s.size(); i++) {
        if(i > 0 && c[sa[i - 1]] == c[sa[i]] && sa[i - 1] + len < (int)s.size() && c[sa[i - 1] + len / 2] == c[sa[i] + len / 2]) {
          classes[sa[i]] = classes[sa[i - 1]];
        } else {
          classes[sa[i]] = i;
        }
      }
      iota(begin(cnt), end(cnt), 0);
      copy(begin(sa), end(sa), begin(c));
      for(int i = 0; i < (int)s.size(); i++) {
        int s1 = c[i] - len;
        if(s1 >= 0) sa[cnt[classes[s1]]++] = s1;
      }
      classes.swap(c);
    }
    s.pop_back();
  }
  // デバッグ用に実装
  void output() {
    cout << "SA\tidx\tstr" << endl;
    for(int i = 0; i < size(); i++) {
      cout << i << ": \t" << sa[i] << " \t" ;
      if(sa[i] != _size) cout << s.substr(sa[i],_size - sa[i]) << endl;
      else cout << "$" << endl;
    }
    cout << endl;
  }
  // sa.size()と表せると便利なので実装
  int size() const{return _size + 1;}
  // sa[]と表せると便利なのでオーバーロードしておく
  int operator[](int k) const{return sa[k]; }
};

struct LCPArray {
  const SuffixArray &SA;
  vector<int> LCP, rank;
  LCPArray(const SuffixArray &sa) : SA(sa) {
    LCP.resize(SA.size()); rank.resize(SA.size());
    // 初期化　rankはsaの逆関数
    for(int i = 0; i < SA.size(); i++) {
      rank[SA[i]] = i;
    }
    LCP[0] = 0; 
    
    // 構築
    for(int i = 0, h = 0; i < SA.size() - 1 ; i++) {
      int j = SA[rank[i] - 1] ; h ? h-- : h;
      // ここで尺取り法に近い手法を使うことでO(N)でLCPの構築をしている
      while( (i > j ? i : j) + h < SA.size() - 1 && SA.s[i + h] == SA.s[j + h] && ++h );
      LCP[rank[i] - 1] = h;
    }
  }

  // デバッグ用に実装
  void output() {
    cout << "SA\tidx\tLCP\tstr" << endl;
     for(int i = 0 ; i < SA.size() ; i++){
      cout << i << "\t" << SA[i] <<" \t" << LCP[i] << "\t"; 
      if(SA[i] == SA.size() - 1) cout << "$";
      else cout << SA.s.substr(SA[i] , SA.size() - 1 - SA[i]);
      cout << endl;
    }
  }

};

// Sparse Table
template<typename T>
struct SparseTable{
  vector< vector< T > > table;
  vector< int > log_table;

  SparseTable(const vector< T > &v) {
    int b = 0;
    while((1 << b) <= (int)v.size()) ++b;
    table.assign(b, vector< T >(1 << b));
    for(int i = 0; i < (int)v.size(); i++) {
      table[0][i] = v[i];
    }
    for(int i = 1; i < b; i++) {
      for(int j = 0; j + (1 << i) <= (1 << b); j++) {
        table[i][j] = min(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);
      }
    }
    log_table.resize(v.size() + 1);
    for(int i = 2; i < (int)log_table.size(); i++) {
      log_table[i] = log_table[i >> 1] + 1;
    }
  }

  // 区間 [l , r) の最小値を返す
  inline T query(int l, int r) {
    int b = log_table[r - l];
    return min(table[b][l], table[b][r - (1 << b)]);
  }
};

// 文字列検索 検索 O(M + logN) メモリO(N logN)
// verify
// https://onlinejudge.u-aizu.ac.jp/status/users/NyaanNyaan/submissions/1/ALDS1_14_D/judge/3874273/C++14
// https://atcoder.jp/contests/abc135/submissions/7574225
// https://judge.yosupo.jp/submission/241
// https://atcoder.jp/contests/abc141/submissions/7577295
struct StringSearch{
  string &s;
  const SuffixArray &sa;
  const LCPArray &lcp;
  SparseTable<int> sparse;
  StringSearch(LCPArray &lcp)
    : s(lcp.SA.s) , sa(lcp.SA) , lcp(lcp) , sparse(lcp.LCP){ }

 // 文字列sの[i , N)と[j , N)の共通接頭辞の長さを求める
  int ArbitaryLCP(int i , int j){
    if(i == j) return (int)(s.size()) - i;
    return sparse.query(
      min(lcp.rank[i] , lcp.rank[j]) , 
      max(lcp.rank[i] , lcp.rank[j])  
    );
  }

  pair<int,int> comp(const string &t  , int len , int si , int ti = 0){
    int sn = (int)s.size() , tn = (int) t.size();
    si += len , ti += len;
    while(si < sn && ti < tn){
      if(s[si] != t[ti]) return make_pair( s[si]<t[ti] , ti);
      si++ , ti++;
    }
    return make_pair( (si>=sn && ti<tn) , ti);
  }  

  pair<int,int> find_range(int left , int med , int right , int len){
    {
      int ng = left - 1, ok = med;
      whlie(ng + 1 < ok){
        int cur = (ng + ok) / 2;
        if(sparse.query(cur , med) >= len) ok = cur;
        else ng = cur;
      }
      left = ok;
    }
    {
      int ok = med , ng = right + 1;
      whlie(ok + 1 < ng){
        int cur = (ng + ok) / 2;
        if(sparse.query(med, cur) >= len) ok = cur;
        else ng = cur;
      }
      right = ok;
    }
    return make_pair(left , right);
  }

  // 全ての出現範囲をSA上の[left , right]の範囲で返す
  // 存在しない場合は-1を返す
  pair<int,int> find(string &t){
    // 条件を満たす[left , right]を見つける
    // sa[0]は空文字列なので left = 1 とする
    // lenは既に一致している文字列の長さ
    int left = 1 , right = sa.size() - 1 , med = left;
    int leftlen = 0 , rightlen = 0 , tlen = t.size();
    pair<int,int> ret;
    while(left + 1 < right){
      med = (left + right) / 2;

      int corres_len = max(
        min(leftlen , sparse.query(left , med)) ,
        min(rightlen, sparse.query(med , right))
      );
      if(corres_len < max(leftlen , rightlen)){
        if(leftlen < rightlen) 
          left = med , leftlen = corres_len;
        else
          right= med ,rightlen = corres_len;
        continue;
      }
      ret = comp(t , corres_len , sa[med]);
      //trc(left,med,right,ret);
      if(ret.second == tlen)
        return find_range(left,med,right,tlen);
      if(ret.first == 0)
        right = med , rightlen = ret.second;
      else
        left = med , leftlen = ret.second;
    }
    if(sa.size() <= 3){
      if(comp(t,0,sa[left]).second==tlen) return find_range(left,left,right,tlen);
      if(comp(t,0,sa[right]).second==tlen) return find_range(left,right,right,tlen);
      return make_pair(-1,-1);
    }
    med = left + right - med;
    ret = comp(t , min(leftlen,rightlen) , sa[med]);
    //trc(left,med,right,ret);
    if(ret.second == tlen)
      return find_range(left,med,right,tlen);
    return make_pair(-1,-1);
  }
};

// Suffix Arrayの使い方(メモリを食うので必要なものだけ使う)
// 参照があるのでstringを削除などしないこと
/*
  SuffixArray sa(S);
  LCPArray lcp(sa);
  StringSearch search(lcp);
*/
// BIT

template< typename T >
struct BIT {
  int N; int max_2beki;

  vector< T > data;
  // 初期化 1-indexedでデータを管理する 0で初期化
  BIT(int size){
      N = ++size;
      data.assign(N, 0);
      max_2beki = 1;
      while(max_2beki * 2 <= N) max_2beki *= 2;
  }

  // [0,k](閉区間)の総和 閉区間に注意！
  T sum(int k) {
    if(k < 0) return 0; // k<0のとき0を返す
    T ret = 0;
    for(++k; k > 0; k -= k & -k) ret += data[k];
    return (ret);
  }

  // [l,r](閉区間)の総和
  inline T sum(int l,int r){
    return sum(r) - sum(l-1);
  }

  // 一点取得 更新はできないことに注意
  inline T operator[](int k){
    return sum(k) - sum(k-1);
  }

  // data[k] += x;
  void add(int k, T x) {
    for(++k; k < N; k += k & -k) data[k] += x;
  }

  // imos法 [l,r]にxを加算
  void imos(int l,int r,T x){
    add(l , x); add(r + 1 , -x);
  }

  // lower_bound sum(i)がval以上となる最小のi
  int lower_bound(T w){
    if(w <= 0) return 0;
    int x = 0;
    for(int k = max_2beki; k > 0; k /= 2){
      if(x+k <= N - 1 && data[x + k] < w){
        w -= data[x + k];
        x += k;
      }
    }
    return x;
  }

  // upper_bound sum(i)がvalより大きくなる最小のi
  int upper_bound(T w){
    if(w < 0) return 0;
    int x = 0;
    for(int k = max_2beki; k > 0; k /= 2){
      if(x+k <= N - 1 && data[x + k] <= w){
        w -= data[x + k];
        x += k;
      }
    }
    return x;
  }

};

void solve(){
  ins(T,S);ini(K);
  int N = sz(S) , M = sz(T);
  int offset = N + 1;
  S += "&";
  S += T;
  SuffixArray sa(S);
  LCPArray lcp(sa);
  //lcp.output();
  StringSearch search(lcp);
  vi left(sz(S) + 1, -1) , right(sz(S) + 1 , -1);
  {
    int cur = -1;
    rep(i,sz(S) + 1){
      left[i] = cur;
      if(sa.sa[i] <= N) cur = i;
    }
  }
  trc(left);
  {
    int cur = -1;
    repr(i,sz(S) + 1){
      right[i] = cur;
      if(sa.sa[i] <= N) cur = i;
    }
  }
  trc(right);
  BIT<int> bit(M + 3);
  vvi g(M + 1);
  for(int i=N+1;i<sz(S);i++){
    trc(left[lcp.rank[i]] , lcp.rank[i] , right[lcp.rank[i]]);
    int len = max(
      (left[lcp.rank[i]]!=-1? 
        search.ArbitaryLCP(sa.sa[left[lcp.rank[i]]],i): 0) ,
      (right[lcp.rank[i]]!=-1? 
        search.ArbitaryLCP(i,sa.sa[right[lcp.rank[i]]]): 0)
    );
    trc(len);
    if(len >= K){
      trc(i + K , i + len - 1);
      g[i-offset].pb(i-offset+K);
      if(K<=len-1) bit.imos( i-offset + K , i-offset + len - 1 , 1);
    }
  }
  rep(i,M){
    if(bit.sum(i)) g[i].pb(i + 1);
  }
  each(x,g) trc(x);
  vi ans(sz(T) + 1 , 0); ans[0] = 1;
  rep(i,sz(T)){
    if(ans[i] == 0) continue;
    each(x , g[i]) ans[x] = 1;
  }
  trc(ans);
  out(ans[sz(T)] ? "Yes" : "No");

}
accuracy: 1
time_ms: 190
memory_kb: 63600
final_rank: 15

code_snippet: #include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <utility>
#define llint long long
#define mod 1000000007
#define inf 1e9

using namespace std;
typedef pair<llint, llint> P;

struct SegTree{
	int size;
	vector<int> seg;

	SegTree(){}
	SegTree(int size){
		this->size = size;
		seg.resize(1<<(size+1));
	}

	void init()
	{
		for(int i = 0; i < (1<<(size+1)); i++) seg[i] = inf;
	}

	void update(int i, int val)
	{
		i += (1 << size);
		seg[i] = val;
		while(i > 1){
			i /= 2;
			seg[i] = min(seg[i*2], seg[i*2+1]);
		}
	}

	int query(int a, int b, int k, int l, int r)
	{
		if(b < l || r < a) return inf;
		if(a <= l && r <= b) return seg[k];
		int lval = query(a, b, k*2, l, (l+r)/2);
		int rval = query(a, b, k*2+1, (l+r)/2+1, r);
		return min(lval, rval);
	}
	int query(int a, int b)
	{
		return query(a, b, 1, 0, (1<<size)-1);
	}
};

int kk, nn;
int Rank[400005];
int tmp[400005];

bool compare_sa(int i, int j)
{
	if(Rank[i] != Rank[j]) return Rank[i] < Rank[j];
	int ri, rj;
	if(i+kk <= nn) ri = Rank[i+kk]; else ri = -1;
	if(j+kk <= nn) rj = Rank[j+kk]; else rj = -1;
	return ri < rj;
}

void makeSA(string s, int sa[]){
	nn = s.size();
	for(int i = 0; i <= nn; i++) sa[i] = i;
	for(int i = 0; i < nn; i++) Rank[i] = s[i];
	s += " ";
	s[nn] = -1;

	for(kk = 1; kk <= nn; kk*=2){
		sort(sa, sa+nn+1, compare_sa);
		int val = 0;
		tmp[sa[0]] = 0;
		for(int i = 1; i <= nn; i++){
			if(compare_sa(sa[i-1], sa[i])) val++;
			tmp[sa[i]] = val;
		}
		for(int i = 0; i <= nn; i++) Rank[i] = tmp[i];
	}
}

void makeLCP(string s, int sa[], int lcp[]){
	nn = s.size();
	for(int i = 0; i <= nn; i++) Rank[sa[i]] = i;

	int h = 0;
	lcp[0] = 0;
	for(int i = 0; i < nn; i++){
		int j = sa[Rank[i]-1];
		while(i+h < nn && j+h < nn && s[i+h] == s[j+h]) h++;
		lcp[Rank[i]-1] = h;
		if(h > 0) h--;
	}
}

string s, t;
int k;
int sa[400005], lcp[400005], sa_inv[400005];
int pred[400005], succ[400005];
int dp[400005];
SegTree seg(19);

int main(void)
{
  ios::sync_with_stdio(0);
  cin.tie(0);

  cin >> s >> t;
  cin >> k;

  string S = s + "#" + t;
  makeSA(S, sa);
  makeLCP(S, sa, lcp);
  for(int i = 0; i <= S.size(); i++) sa_inv[sa[i]] = i;

  /*for(int i = 0; i <= S.size(); i++){
    cout << i << " " << S.substr(sa[i]) << " " << lcp[i] << endl;
  }*/

  int x = -1;
  for(int i = 0; i <= S.size(); i++){
    pred[i] = x;
    if(sa[i] > s.size()) x = i;
  }
  x = S.size()+1;
  for(int i = S.size(); i >= 0; i--){
    succ[i] = x;
    if(sa[i] > s.size()) x = i;
  }

  seg.init();
  for(int i = 0; i <= S.size(); i++) seg.update(i, lcp[i]);

  int n = s.size();
  s = "#" + s; int sum = 0;
  dp[0] = 1, dp[1] = -1;
  for(int i = 0; i <= n; i++){
    sum += dp[i];
    if(sum == 0) continue;
    int mx = 0, pos = sa_inv[i];
    if(pred[pos] >= 0){
      mx = max(mx, seg.query(pred[pos], pos-1));
    }
    if(succ[pos] <= S.size()){
      mx = max(mx, seg.query(pos, succ[pos]-1));
    }
    //cout << i << " " << pos << " " << pred[pos] << " " << succ[pos] << " " << mx << endl;
    if(mx < k) continue;
    dp[i+k]++, dp[i+mx+1]--;
  }
  if(sum) cout << "Yes" << endl;
  else cout << "No" << endl;

  return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 19140
final_rank: 11

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define mod 1000000007
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
class suffixarray{
public:
    int sz,index1,index2;
    vector<int> rnk,tmp,sa,lcp;
    string recs;
    suffixarray(string s){
        recs = s;
        sz = (int)s.size();
        rnk.resize(sz+1),tmp.resize(sz+1);
        make_sa();
        make_lcp();
    }
    void make_sa(){
        index1 = sz;
        sa.resize(index1+1);
        for(int i = 0; i < index1+1; i++){
            sa[i] = i;
            rnk[i] = i<index1?recs[i]:-1;
        }
        auto comp = [&](int i,int j){
            if(rnk[i] != rnk[j]){
                return rnk[i] < rnk[j];
            }else{
                int ri = (i+index2<=index1)?rnk[i+index2]:-1;
                int rj = (j+index2<=index1)?rnk[j+index2]:-1;
                return ri < rj;
            }
        };
        for(index2=1;index2<=index1;index2*=2){
            sort(sa.begin(),sa.end(),comp);
            tmp[sa[0]] = 0;
            for(int i=1;i<=index1;i++){
                tmp[sa[i]] = tmp[sa[i-1]]+(comp(sa[i-1],sa[i])?1:0);
            }
            for(int i = 0; i < index1+1; i++){
                rnk[i] = tmp[i];
            }
        }
    }
    void make_lcp(){
        lcp.resize(sz+1);
        for(int i = 0; i < sz+1; i++){
            rnk[sa[i]] = i;
        }
        int h = 0;
        lcp[0] = 0;
        for(int i = 0; i < sz; i++){
            int j = sa[rnk[i]-1];
            if(h > 0){
                h--;
            }
            for(;j+h<sz&&i+h<sz;h++){
                if(recs[j+h] != recs[i+h]){
                    break;
                }
            }
            lcp[rnk[i]-1] = h;
        }
    }
};
int main(){
    string s,t;
    cin >> s >> t;
    int n = s.size();
    int m = t.size();
    int sz = s.size()+t.size()+1;
    string p = s + "~" + t;
    int a = s.size();
    int b = t.size();
    suffixarray SA(p);
    vector<int> sa = SA.sa;
    vector<int> lcp = SA.lcp;
    sz = sa.size();
    // rep(i,sz){
    //     cerr << sa[i] << " " << lcp[i] << endl;
    //     cerr << p[sa[i]] << endl;
    // }
    vector<int> flag(sz+100000);
    rep(i,sz){
        if(sa[i]>=a+1&&sa[i]<a+1+b){
            //cerr <<sa[i] << " " << p[sa[i]] << endl;
            flag[i] = true;
        }
    }
    vector<int> len(a+100000);
    int tmp = 0;
    rep(i,sz){
        if(flag[i]){
            tmp = lcp[i];
        }else{
            len[sa[i]] = max(len[sa[i]],tmp);
            tmp = min(tmp,lcp[i]);
        }
    }
    int k;
    cin >> k;
    
    tmp = 0;
    rep(i,sz){
        if(flag[sz-1-i]){
            if(sz-2-i<0)continue;
            tmp = lcp[sz-2-i];
        }else{
            len[sa[sz-1-i]] = max(len[sa[sz-1-i]],tmp);
            if(i!=sz-1)tmp = min(tmp,lcp[sz-2-i]);
        }
    }
    // rep(i,a){
    //     cout << len[i] << endl;
    // }
    
    // if(k!=4&&k!=1){
    //     cout << "WA" << endl;
    //     return 0;
    // }
    vector<int> dp(a+100000);
    dp[a] = 1;
    vector<int> dp2(a+300000);
    dp2[a] = 1;
    
    for(int i=sz-1;i>=0;i--){
        dp2[i] += dp2[i+1];
        
        if(len[i]<k)continue;
        
        if(len[i]>=k){
            if(dp2[i+k]-dp2[i+len[i]+1]>0){
                dp[i] = 1;
            }
            // for(int j=i+k;j<=i+len[i];j++){
            //     if(dp[j]){
            //         dp[i] = true;
            //         break;
            //     }
            // }
        }
        dp2[i] += dp[i];
    }
    if(dp[0]){
        cout << "Yes" << endl;
    }else{
        cout << "No" << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 19504
final_rank: 7