题意:给你一个1e4长的字符串S,有1e5个询问,每个询问形如 l r c ,其中l,r为左右边界,c为所询问的字符。注意,l,r,可以大于串S的长度,这种情况下认为S自身重复无数次(S+S+S···)。l,r范围1e9。
题解:预处理前缀和(多处理一下),先打表dp[256][10005],dp['a'][x]代表1~x中'a'出现几次,有dp[s[i-1]][i]=dp[s[i-1]][i-1]。然后输出区间时直接输出sum(r)-sum(l),其中sum(x)为计算1~x区间某字符串出现的次数。
坑点:cin,cout用一个就会T。不用前缀和会wa...可能打错了什么。还有这个表达式a[c][n] *( x / n)不遵守交换律
ac代码:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string> #include<string.h> #include<stdio.h> using namespace std; const int maxn = 1e4 + 5; int n, q; int a[256][maxn]; int sum(int x,char c) { int ans=0; ans = a[c][n] *( x / n); x %= n; ans += a[c][x]; return ans; }; int main() { int t; cin >> t; while (t--) { memset(a, 0, sizeof(a)); cin >> n >> q; string s; cin >> s; a[s[0]][1]++; for (int i = 2; i <= n; i++) { for (int j = 'a'; j <= 'z'; j++) { a[j][i] = a[j][i - 1]; } a[s[i - 1]][i] = a[s[i - 1]][i - 1] + 1; } for (int i = 1; i <= q; i++) { int l, r; scanf("%d%d", &l, &r); int x = l / n + 1, y = r / n; int z = y - x; //l %= n; r %= n; char c[5]; scanf("%s", c); printf("%d ",sum(r,c[0]) - sum(l-1,c[0])); } }