https://vjudge.net/contest/299247#problem/K
分类讨论
其中一种情况是这样的,求字符串中所有回文子串的数目
Manacher是求字符串最长回文子串的算法,在求解过程中会记录一个len数组,保存以每个字符为中心点的回文串最大长度(此长度包含‘#’),我们利用这个len数组,很容易求得以每个字符为中心的回文串数目(len / 2),加起来就是要求的回文子串总数。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 2000005;
char s[maxn << 1];
char s1[maxn << 1];
char m[maxn << 1];
int len[maxn << 1];
char tmp[maxn << 1];
void Manacher(char s[], int leng)
{
int l = 0;
m[l ++] = '$';
m[l ++] = '#';
for(int i = 0; i < leng; i ++)
{
m[l ++] = s[i];
m[l ++] = '#';
}
m[l] = 0;
int mx = 0, id = 0;
for(int i = 0; i < l; i ++)
{
len[i] = mx > i ? min(len[2*id-i], mx-i) : 1;
while(m[i+len[i]] == m[i-len[i]])
len[i] ++;
if(i + len[i] > mx)
{
mx = i + len[i];
id = i;
}
}
}
int main()
{
int t;
scanf("%d", &t);
while(t --)
{
scanf("%s%s", s, s1);
int lens = strlen(s);
if(strcmp(s, s1) == 0)
{
Manacher(s, lens);
ll ans = 0;
for(int i = 0; i <= 2 * lens + 1; i ++)
{
ans += len[i] / 2;
}
printf("%lld\n", ans);
continue;
}
int left = -1, right = -2;
for(int i = 0; i < lens; i ++)
{
if(s[i] != s1[i])
{
left = i;
break;
}
}
for(int i = lens - 1; i >= 0; i --)
{
if(s[i] != s1[i])
{
right = i;
break;
}
}
strcpy(tmp, s);
for(int i = 0; i < right - left + 1; i ++)
{
//tmp[right - i] = s[i + left];
tmp[i + left] = s[right - i];
}
//printf("%s\n", tmp);
tmp[lens] = '\0';
if(strcmp(tmp, s1) == 0)
{
int ans = 1;
left --, right ++;
while(left >= 0 && right < lens)
{
if(s[left] == s[right])
ans ++;
else break;
left --;
right ++;
}
printf("%d\n", ans);
}
else
{
printf("0\n");
}
}
return 0;
}