1 条题解

  • 0
    @ 2026-8-27 14:45:41

    大写字母 A-Z 表示关键字、常量等非变量符号,必须精确匹配,小写字母 a-z 表示变量名,匹配时只需要满足变量名的替换关系一致。

    我们需要判断两个字符串在变量名替换意义下是否等价。关键在于:对于每个变量名(小写字母),它在当前位置与上一次出现的位置的距离应该相同。

    对于每个位置,如果是大写字母,直接记录其负值,这样既可以比较是否相等,还不用考虑大小写冲。

    如果是小写字母,记录该字母距离上一次出现的位置的距离(如果是第一次出现,距离就是当前位置)。

    然后跑 kmp,对于大写字母必须精确相等,对于小写字母需要满足相同的距离关系。

    时间复杂度是 O(S+T)O(|S| + |T|),与标准 KMP 算法相同。

    代码实现:

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N = 1e6 + 5, M = 35;
    int q, n, m, nxt[N], a[N], b[N], w[M];
    string s, t;
    inline bool check(int a, int b, int c){
        if(a == b) return true;
        return a > c && b > c;
    }
    inline void init(){
        for(int i = 0; i <= 27; i++) w[i] = 0;
    }
    inline int kmp(){
        int res = 0;
        for(int i = 2, j = 0; i <= m; i++){
            while(j && !check(b[j + 1], b[i], j)) j = nxt[j];
            if(check(b[j + 1], b[i], j)) j++;
            nxt[i] = j;
        }
        for(int i = 1, j = 0; i <= n; i++){
            while(j && !check(b[j + 1], a[i], j)) j = nxt[j];
            if(check(b[j + 1], a[i], j)) j++;
            if(j == m) res++, j = nxt[m];
        }
        return res;
    }
    inline void solve(){
        nxt[1] = 0;
        cin >> s >> t;
        s = " " + s, t = " " + t, n = s.size() - 1, m = t.size() - 1;
        init();
        for(int i = 1; i <= n; i++){
            if(s[i] < 'a') a[i] = -(s[i]);
            else a[i] = i - w[s[i] - 'a' + 1], w[s[i] - 'a' + 1] = i;
        }
        init();
        for(int i = 1; i <= m; i++){
            if(t[i] < 'a') b[i] = -(t[i]);
            else b[i] = i - w[t[i] - 'a' + 1], w[t[i] - 'a' + 1] = i;
        }
        cout << kmp() << "\n";
        return ;
    }
    signed main(){
        ios::sync_with_stdio(0);
        cin.tie(0), cout.tie(0);
        cin >> q;
        while(q--) solve();
        return 0;
    }
    
    • 1

    信息

    ID
    6127
    时间
    2000ms
    内存
    250MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者