题目描述
对于一对字符串
现在给出一对
答案对
输入格式
第一行两个整数,
第二行两个字符串,
输出格式
一行一个整数,表示
样例 #1
样例输入 #1
10 2 ccbccbbcbb bc
样例输出 #1
4
样例 #2
样例输入 #2
20 2 cbcaacabcbacbbabacca ba
样例输出 #2
4
提示
【样例解释】
对于样例一:
子串
子串
【数据范围】
- 对于
的数据: ,字符串中的字符都是小写字母。
分析
KMP 算法预处理出每一个字串
对于每一个点
如回文串 abcbcba
,我们查找串 abcbcba
,只要用
对于上面的整个回文串来说,最后的结果就是
算法实现
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #define ll long long using namespace std; const int N = 4e6 + 10; char s[N], p[N]; ll nextval[N], t[N], plc[N], n, m, ans; void sum() { for (ll i = 2; i <= n; ++i) plc[i] += plc[i - 1]; } inline void getNext() { int j = 0; for (int i = 2; i <= n; ++i) { while (j && p[j + 1] != p[i]) j = nextval[j]; if (p[j + 1] == p[i]) ++j; nextval[i] = j; } } inline void KMP() { getNext(); long long int j = 0; for (register long long int i = 1; i <= n; ++i) { while (j && p[j + 1] != s[i]) j = nextval[j]; if (p[j + 1] == s[i]) ++j; if (j == m) { j = nextval[j]; ++plc[i - m + 1]; } } } void manacher() { for (int i = 1, l = 1, r = 0; i <= n; ++i) { ll ml = l + r - i; t[i] = max(min(t[ml], 1LL * r - i + 1), 1LL); if (ml - t[ml] < l) { while (i - t[i] > 0 && i + t[i] <= n && s[i + t[i]] == s[i - t[i]]) t[i]++; l = i - t[i] + 1, r = i + t[i] - 1; } } } void getAns() { ll mid = (m + 1) >> 1; for (int i = mid; i <= n; ++i) { if ((t[i] << 1) - 1 < m) continue; ans += (plc[i - m + t[i]] - plc[i - m + mid - 1]); ans -= (plc[i - mid] - plc[i - t[i] - 1]); } ll MOD = pow(2, 32); cout << ans % MOD << endl; } void solve() { scanf("%lld %lld", &n, &m); scanf("%s %s", s + 1, p + 1); s[0] = '#'; KMP(); sum(); sum(); manacher(); getAns(); } int main() { int T = 1; // cin >> T; while (T--) { solve(); } return 0; }