nowcoder 2020牛客NOIP赛前集训营-提高组(第五场)T2 K匹配
Description–
给定一个字符串
S
S
S和一个字符串
T
T
T,如果
S
S
S存在一个长度为
k
k
k的子串
S
l
1
,
l
1
+
k
−
1
S_{l_1, l_1 + k - 1}
Sl1,l1+k−1 和
T
T
T的某个长度为
k
k
k的子串
T
l
2
,
l
2
+
k
−
1
T_{l_2,l_2 + k - 1}
Tl2,l2+k−1 相等,那么我们就认为字符串
S
S
S和字符串
T
T
T是
k
k
k匹配的。
比如字符串
a
b
a
c
c
abacc
abacc和字符串
d
d
a
b
a
c
k
k
ddabackk
ddabackk就是
4
4
4匹配的。
给定一个长度为 n n n的字符串 S S S和一个长度为 k k k的字符串 T T T,求 S S S有多少个子串和 T T T是满足 k k k匹配的。
Input–
第一行两个整数
n
,
k
n, k
n,k分别表示字符串
S
S
S的长度和字符串
T
T
T的长度。
第二行一个长度为
n
n
n的字符串表示
S
S
S。
第三行一个长度为
k
k
k的字符串表示
T
T
T。
保证字符串
S
S
S和
T
T
T中只包含小写字母。
Output–
输出一行整数表示 S S S中满足和 T T T是 k k k匹配的子串个数。
Sample Input–
10 2
abaaaababa
ab
Sample Output–
33
说明–
对于
20
%
20 \%
20%的数据满足
1
≤
k
≤
n
≤
500
1 \leq k \leq n \leq 500
1≤k≤n≤500
对于
40
%
40\%
40%的数据满足
1
≤
k
≤
n
≤
5000
1 \leq k \leq n \leq 5000
1≤k≤n≤5000
对于
60
%
60\%
60%的数据满足
1
≤
k
≤
n
≤
1
0
6
1 \leq k \leq n \leq 10^6
1≤k≤n≤106
对于
100
%
100\%
100%的数据满足
1
≤
k
≤
n
≤
1
0
7
1 \leq k \leq n \leq 10^7
1≤k≤n≤107
解题思路–
用数值表示出每个子串再判断(131进制,用ull自然溢出(算是哈希吧))即可优化
代码–
暴力做法
O(nk)。。。不知道怎么就过了(牛客数据点有.水。。)
#include <iostream>
#include <cstring>
#include <cstdio>
#define ll long long
using namespace std;
ll ans;
int n, k, l, r, lr;
string s, t;
bool check(int x)
{
for (int i = 0; i < k; ++i)
if (s[i + x] != t[i]) return 0;
return 1;
}
int main()
{
scanf("%d%d", &n, &k);
getchar(); getline(cin, s);
getline(cin, t);
for (int i = 1; i <= n - k + 1; ++i)
{
if (!check(i - 1)) continue;
l = i - lr;
r = n - (i + k - 1) + 1;
ans += (ll)l * (ll)r, lr = i;
}
printf("%lld", ans);
return 0;
}
正解
QAQ
#include <iostream>
#include <cstring>
#include <cstdio>
#define ull unsigned long long
using namespace std;
ull tt, kk = 1, ans, h[10000005];
int n, k, l, r, lr;
string s, t;
bool check(int x)
{
ull xx = h[x + k - 1];
ull yy = h[x - 1];
yy = xx - yy * kk;
return yy == tt;
}
int main()
{
scanf("%d%d", &n, &k);
getchar(); getline(cin, s);
getline(cin, t);
for (int i = 0; i < n; ++i)
h[i] = h[i - 1] * 131 + (int)(s[i] - 'a' + 1);
for (int i = 0; i < k; ++i)
{
tt = tt * 131 + (int)(t[i] - 'a' + 1);
kk = kk * 131;
}
for (int i = 1; i <= n - k + 1; ++i)
{
if (!check(i - 1)) continue;
l = i - lr;
r = n - (i + k - 1) + 1;
ans += (ull)l * (ull)r, lr = i;
}
printf("%lld", ans);
return 0;
}