Today we virtually participated the regional of 2018 Nanjing, and I
have done my first non-trivial string problem, introducing a new
algorithm called Extended-KMP. Thus I bet it notable on by blog.
Problem Statement
Given two strings s and t, count the number of tuples such that
The -th character of to the -th character of , concatenated with the first character
of to the -th character of , is a palindrome.
,
Solution
The problem is to find and count the number of cases that there is
two adjacent substrings ,
in and another in , provided that is a palindrome, and is reversely matched with .
So let's reverse the string .
Then use the famous Manacher algorithm on (when there is a longest palindrome
, let ) and
count every occurrence centered at .
Let be the suffix of starting from . We should firstly find the longest
common prefix of suffix and
, and sum up the length of these
prefixes around . Precisely, all
of the prefixes starting from
to should be counted.
Using prefix sum, we could get that value in at every symmetrical center.
It must be noted that , then must not be empty.
Dealing with bounds and indexes of strings is tricky, so be
careful.
#include<bits/stdc++.h> usingnamespace std; constintMaxN(2e6+10); char s[MaxN], t[MaxN]; int palin[MaxN]; // the half length of palindrome centered at i/2 voidmanacher(char str[], int len[], int n){ len[0] = 1; for (inti(1), j(0); i < (n << 1) - 1; ++i) { intp(i >> 1), q(i - p), r(((j + 1) >> 1) + len[j] - 1); len[i] = r < q ? 0 : min(r - q + 1, len[(j << 1) - i]); while (p > len[i] - 1 && q + len[i] < n && str[p - len[i]] == str[q + len[i]]) ++len[i]; if (q + len[i] - 1 > r) j = i; } } // Extended KMP voidGetNext(char *T, int & m, int next[]){ int a = 0, p = 0; next[0] = m; for (int i = 1; i < m; i++) { if (i >= p || i + next[i - a] >= p) { if (i >= p) p = i; while (p < m && T[p] == T[p - i]) p++; next[i] = p - i; a = i; } else next[i] = next[i - a]; } } voidGetExtend(char *S, int & n, char *T, int & m, int extend[], int next[]){ int a = 0, p = 0; GetNext(T, m, next); for (int i = 0; i < n; i++) { if (i >= p || i + next[i - a] >= p) { if (i >= p) p = i; while (p < n && p - i < m && S[p] == T[p - i]) p++; extend[i] = p - i; a = i; } else extend[i] = next[i - a]; } } int Next[MaxN], Lcsp[MaxN]; // longest common prefix of suffix s_i and t using LL = longlong; LL SLcsp[MaxN]; // prefix sum of Lcsp intmain(){ scanf("%s", s); scanf("%s", t); intls(strlen(s)), lt(strlen(t)); // reverse the string s for (inti(0); i < ls / 2; ++i) { swap(s[i], s[ls - i - 1]); } manacher(s, palin, ls); GetExtend(s, ls, t, lt, Lcsp, Next); // prefix sum for (inti(0); i < ls; ++i) { SLcsp[i + 1] = SLcsp[i] + Lcsp[i]; } LL ans(0); for (inti(0); i < ls + ls - 1; ++i) { if (i & 1) { // even length palindrome intmid((i + 1) / 2); // to exclude empty palindrome part ans += SLcsp[min(mid + palin[i] + 1, ls)] - SLcsp[mid + 1]; } else { // odd length palindrome intmid(i / 2); ans += SLcsp[min(mid + palin[i] + 1, ls)] - SLcsp[mid + 1]; } } printf("%lld\n", ans); return0; }
预览: