Gym100548G-The Problem to Slow Down You

题意:给你两个长度不超过20W的字符串, 都只包含小写字母, 求相同的回文串对数 (S, T), 其中S == T, S来自第一个字符串, T来自第二个字符串, S和T都是回文串

解题思路:对两个字符串都建回文树,然后对回文树进行dfs即可


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;
const int maxn = 1e6 + 10;

char s[maxn];
LL ans;

struct PalindromicTree
{
	const static int maxn = 1e6 + 10;
	int next[maxn][26], last, sz, tot;
	int fail[maxn], len[maxn];
	LL cnt[maxn];
	char s[maxn];
	void Clear()
	{
		len[1] = -1; len[2] = 0;
		fail[2] = fail[1] = 1;
		last = (sz = 3) - 1;
		cnt[1] = cnt[2] = tot = 0;
		memset(next[1], 0, sizeof(next[1]));
		memset(next[2], 0, sizeof(next[2]));
	}
	int Node(int length)
	{
		memset(next[sz], 0, sizeof(next[sz]));
		len[sz] = length, cnt[sz] = 1;
		return sz++;
	}
	int getfail(int x)
	{
		while (s[tot] != s[tot - len[x] - 1]) x = fail[x];
		return x;
	}
	int add(char pos)
	{
		int x = (s[++tot] = pos) - 'a', y = getfail(last);
		if (next[y][x]) return ++cnt[last = next[y][x]];
		last = next[y][x] = Node(len[y] + 2);
		fail[last] = len[last] == 1 ? 2 : next[getfail(fail[y])][x];
		return cnt[last];
	}
	void work()
	{
        for(int i=sz-1;i>2;i--)
            if(fail[i]>2) cnt[fail[i]]+=cnt[i];
	}
}solve[2];

void dfs(int x,int y)
{
    ans+=solve[0].cnt[x]*solve[1].cnt[y];
    for(int i=0;i<26;i++)
        if(solve[0].next[x][i]&&solve[1].next[y][i]) dfs(solve[0].next[x][i],solve[1].next[y][i]);
}

int main()
{
    int t,cas=0;
    scanf("%d",&t);
	while(t--)
	{
        for(int i=0;i<2;i++)
        {
            solve[i].Clear();
            scanf("%s",s);
            for(int j=0;s[j];j++) solve[i].add(s[j]);
            solve[i].work();
        }
        ans=0;
        for(int i=1;i<=2;i++) dfs(i,i);
        printf("Case #%d: %lld\n",++cas,ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>