P5555 秩序魔咒

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43544481/article/details/102770274

题意:给你两个字符串,求出这两个字符串的最长公共回文子串长度和个数

题解:我们可以对这两个字符串分别建回文树,然后同时进行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);
}

猜你喜欢

转载自blog.csdn.net/qq_43544481/article/details/102770274