题意:给你两个字符串,求出这两个字符串的最长公共回文子串长度和个数
题解:我们可以对这两个字符串分别建回文树,然后同时进行dfs,走相同的转移边,得到的回文串显然是相同的,由于回文串的长度可以为奇数也可以为偶数,所以我们需要对奇根节点和偶根节点进行dfs,就可以找到最长公共回文子串长度了,至于个数,由于在回文树中,每个回文串一定是不同的,所以也可以统计出不同最长公共回文子串的个数
#include<bits/stdc++.h>
using namespace std;
const int MAXNODE = 3e5+50;
int Max = 0,tot = 0;
struct Palion{
int nxt[MAXNODE][26],fail[MAXNODE],len[MAXNODE],cnt[MAXNODE];
int sz,lst;
char s[MAXNODE];
void Init(char *str){
sz = lst = 1;
len[1] = -1,len[0] = 0;
fail[0] = 1,fail[1] = 0;
for(int i=1;str[i];i++) s[i]=str[i];
}
void Insert(char ch,int en){
int root = lst;
while(s[en]!=s[en-len[root]-1]) root = fail[root];
if(!nxt[root][ch-'a']){
len[++sz] = len[root] + 2;
int tmp = fail[root];
while(s[en]!=s[en-len[tmp]-1]) tmp = fail[tmp];
fail[sz] = nxt[tmp][ch-'a'];
cnt[sz] = cnt[fail[sz]] + 1;
nxt[root][ch-'a'] = sz;
}
lst = nxt[root][ch-'a'];
}
}PAM1,PAM2;
void dfs(int x,int y){
if(Max < PAM1.len[x]) Max = PAM1.len[x],tot = 1;
else if(Max == PAM1.len[x]) ++tot;
for(int i=0;i<26;i++)
if(PAM1.nxt[x][i] && PAM2.nxt[y][i])
dfs(PAM1.nxt[x][i],PAM2.nxt[y][i]);
}
int n,m;
char str1[MAXNODE],str2[MAXNODE];
int main(){
scanf("%d%d",&n,&m);
scanf("%s%s",str1+1,str2+1);
PAM1.Init(str1),PAM2.Init(str2);
for(int i=1;str1[i];i++) PAM1.Insert(str1[i],i);
for(int i=1;str2[i];i++) PAM2.Insert(str2[i],i);
dfs(0,0),dfs(1,1);
printf("%d %d\n",Max,tot);
}