思路:由题意可知,回文的中心一定在s所取的部分中,然后可以想到 s [ i . . . k ] s[i...k] s[i...k]必定和 t [ 1... k ] t[1...k] t[1...k]是lcp(s中是倒着匹配),并且 s [ k + 1... j ] s[k+1...j] s[k+1...j]也需要是回文。所以可以枚举s中每个点为断点,用hash和二分求出lcp,并在Manacher算法中预处理出每个断点右边相邻的回文串的个数。
char s[N<<1], t[N];
int lens, lent;
ll p1[N], p2[N], h1[N], h2[N], h3[N], h4[N];
void initbase()
{
p1[0] = p2[0] = 1;
f(i, 1, N-1)
{
p1[i] = p1[i - 1] * 377 % mod;
p2[i] = p2[i - 1] * 377 % mod2;
}
reverse(s + 1, s + lens + 1);
for (int i = 1;i <= lens;i++)
h1[i] = (h1[i - 1] * 377 + s[i]) % mod,
h2[i] = (h2[i - 1] * 377 + s[i]) % mod2;
for (int i = 1;i <= lent;i++)
h3[i] = (h3[i - 1] * 377 + t[i]) % mod,
h4[i] = (h4[i - 1] * 377 + t[i]) % mod2;
}
ll pre_of_suf(int x, int y)
{
ll t1 = (h1[lens - x + 1] - (ll)h1[lens - y] * p1[y - x + 1] % mod + mod) % mod;
ll t2 = (h2[lens - x + 1] - (ll)h2[lens - y] * p2[y - x + 1] %mod2 + mod2) % mod2;
return t1 << 31 | t2;
}
ll suf_of_pre(int x, int y)
{
ll t1 = (h3[y] - (ll)h3[x-1] * p1[y - x + 1] % mod + mod) % mod;
ll t2 = (h4[y] - (ll)h4[x-1] * p2[y - x + 1] % mod2 + mod2) % mod2;
return t1 << 31 | t2;
}
int tree[N],fin[N];
void add(int k, int num)
{
for (int i = k;i <= N; i += i & -i)
tree[i] += num;
}
int read(int k)
{
int sum = 0;
for (int i = k;i > 0; i -= i & -i)
sum += tree[i];
return sum;
}
char Ma[N << 1], ss[N];
int r[N << 1];
void Manacher(char s[], int len)
{
int l = 0;
Ma[l++] = '$';
Ma[l++] = '#';
for (int i = 0;i <len;i++)
{
Ma[l++] = s[i];
Ma[l++] = '#';
}
Ma[l] = 0;
int mx = 0, id = 0;
for (int i = 0;i < l;i++)
{
r[i] = mx > i ? min(r[2 * id - i], mx - i) : 1;
while (Ma[i + r[i]] == Ma[i - r[i]])r[i]++;
if (i + r[i] > mx)
{
mx = i + r[i];
id = i;
}
}
int idx = 0;
f(i, 2, l - 1)
{
if (Ma[i] != '#')idx++;
if (r[i] == 1)continue;
int L = idx - r[i]/2+1, R = idx;
add(L, 1);//树状数组区间算贡献
add(R+1, -1);
}
f(i, 1, lens)fin[i] = read(i);
}
int main()
{
//freopen("in.txt", "r", stdin);
scanf("%s%s", s + 1, t + 1);
strcpy(ss + 1, s + 1);
lens = strlen(s + 1);lent = strlen(t + 1);
Manacher(s + 1, lens);
initbase();
ll ans = 0;
//f(i, 1, lens)debug(fin[i + 1]);
f(i, 1, lens-1)
{
if (ss[i] != t[1])continue;
int l = 1, r = min(lent, i);
ll res = 1;
while (l <= r)
{
int mid = l + r >> 1;
if (suf_of_pre(1, mid) == pre_of_suf(i - mid + 1, i))
{
res = mid;
l = mid + 1;
}
else r = mid - 1;
}
ans += fin[i + 1] * res;
}
cout << ans << endl;
return 0;
}