1 条题解
-
0
大写字母
A-Z表示关键字、常量等非变量符号,必须精确匹配,小写字母a-z表示变量名,匹配时只需要满足变量名的替换关系一致。我们需要判断两个字符串在变量名替换意义下是否等价。关键在于:对于每个变量名(小写字母),它在当前位置与上一次出现的位置的距离应该相同。
对于每个位置,如果是大写字母,直接记录其负值,这样既可以比较是否相等,还不用考虑大小写冲。
如果是小写字母,记录该字母距离上一次出现的位置的距离(如果是第一次出现,距离就是当前位置)。
然后跑 kmp,对于大写字母必须精确相等,对于小写字母需要满足相同的距离关系。
时间复杂度是 ,与标准 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
- 上传者