M - Mediocre String Problem( 扩展KMP + Manacher + 差分 )

M - Mediocre String Problem( 扩展KMP + Manacher + 差分 )

题意:给出一个串S,和一个串T. 要求 从S串中取一个子串,后面接上T串的一个前缀 组成一个结果串,(要求S串的部分比T串的部分长),结果串是回文串的个数。

M - Mediocre String Problem( 扩展KMP + Manacher + 差分 )_第1张图片

思路:

S串贡献的部分 可以分成两部分,S1+S2;

前面的S1 是T部分的反转;

S2 就只能是回文串,因为S串的部分必须比T的多,所以S2长度必须大于等于1

然后我们可以分成两部分,首先先把S中的所有回文串求出,可以用(回文树/马拉车/字符串哈希)

对于每一个回文串,它的左边半径部分都可以作为S1的右端点,除了中心,而且边缘也可以吃到一个

比如 CABABA 其中 回文串中心是第二个A,S1的右端点可以是CAB 注意C也可以的哦

然后找出这个端点剩下的就是求S1和T的lcp的长度了,根据题意每一个长度都一个贡献一个符合要求的答案

针对这个问题 我们可以把S 反转 和T用EXKMP 求lcp (也可以用后缀数组/字符串哈希/exkmp/后缀自动机)

所以 这题的解法大概有(3×3=9 或者3×4=12)种。

注意:使用差分优化,开long long

代码:

#include
#define int long long

using namespace std;

const int maxn = 2000006;
char s[maxn],ss[maxn],t[maxn];
int nxt[maxn],extend[maxn];
char Ma[maxn*3];
int Mp[maxn*3];
int st[maxn*3];

void get_nxt()
{
    int len = strlen(t);
    nxt[0] = len;
    int j = 0;
    while ( j+1i?min(Mp[2*id-i],mx-i):1;
        while ( Ma[i+Mp[i]]==Ma[i-Mp[i]] ) Mp[i]++;
        if ( i+Mp[i]>mx ) {
            mx = i+Mp[i];
            id = i;
        }
    }
    int ans = 0;
    for ( int i=1; i0 ) ans+=extend[i/2]*now;
    }
    cout << ans << endl;
}

signed main()
{
    scanf("%s %s",ss,t);
    int len = strlen(ss);
    for ( int i=0; i

 

你可能感兴趣的:(字符串补题)