AFO

秩序魔咒

Description

给出两个字符串,求出两个字符串的共同回文子串的最长长度和合法且最长的不同子串数量


四舍五入大概是道语文题

先跑一遍马拉车,求以每个位置为中心的最长回文串长度

然后二分长度顺便求一下第二问

我 不 会 写 哈 希 表 啊

怎 么 世 界 对 map 这 么 这 么 不 友 好 啊

只T第一个只有5分subtask克海星(Subtask #1是样例,0分那种

可恶的是这还是赛多乐赛制


#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
#define ULL unsigned long long 
using namespace std;
const int base=37;
const int M = 600001;
int n,m,k,p[M],ans,res,w[2][M];
char c[M],s[M];
ULL u[2][M],d[M];
map<ULL,int>mp;
void manacher(int k)
{
    int l=strlen(s+1),mid=0,r=0; 
    memset(p,0,sizeof(p));
    c[1]='#';
    for(int i=1;i<=l;i++) 
    {
        c[i*2]=s[i];
        c[i*2+1]='#';	
    }
    l=l*2+1;
    for(int j=1;j<=l;j++) 
	{
		if(j) u[k][j]=u[k][j-1]*base;
		if(c[j]!='#') u[k][j]+=c[j]-'a'+1; 
		else u[k][j]+=27;
	}
    for(int i=1;i<=l;i++)
    {
        p[i]=r>i ? min(p[2*mid-i],r-i):1;
        while(c[i+p[i]]==c[i-p[i]]) p[i]++;
        if(r<i+p[i]) r=i+p[i], mid=i;
        w[k][i]=p[i];
    }
}

int check(int k)
{
	mp.clear();
	k+=1;
	int res=0;
	for(int i=1;i<=n*2;i++)
	{
		if(w[0][i]<k) continue;
		ULL U=u[0][i+k-1]-u[0][i-k]*d[k-1+k];    
		if(mp.find(U)==mp.end()) mp[U]=1;
	}
	for(int i=1;i<=m*2;i++)
	{
		if(w[1][i]<k) continue;
		ULL U=u[1][i+k-1]-u[1][i-k]*d[k-1+k];   
		if(mp.find(U)==mp.end() || mp[U]==0) continue;
		mp[U]=0; res+=1; 
	}
	return res;
}

void solve()
{
	int l=1,r=n, tmp1,tmp2,mid;
	while(l<=r)
	{
		mid=(l+r)>>1;
		tmp2=check(mid);
		if(tmp2) ans=mid,res=tmp2,l=mid+1;
		else r=mid-1;
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	d[0]=1;
	for(int i=1;i<M;i++) d[i]=d[i-1]*base;
	scanf("\n%s",s+1);
	manacher(1);
	scanf("\n%s",s+1);
	manacher(0);
	solve();
	printf("%d %d",ans,res);
 }
posted @ 2019-09-08 20:49  ZUTTER☮  阅读(133)  评论(0编辑  收藏  举报