1. 程式人生 > 其它 >icpc2018南京 M Mediocre String Problem(exkmp+mamacher)

icpc2018南京 M Mediocre String Problem(exkmp+mamacher)

題意:

給出2個串s和t

要求從s中選出連續一段區間[i,j],拼接上t的前k個字元是迴文串

且區間[i,j]長度要大於k

問三元組(i,j,k)有多少種

s中選出的區間長度要大於t的字首,且要拼接出來是迴文串

等價於

s選出的區間中,後一塊是自迴文的,前一塊拼上t的字首是迴文串

等價於

s選出的區間中,後一塊是自迴文的,前一塊的反串等於t的字首

如圖所示

假設我們求出了s的所有迴文串,並且可以列舉每個迴文串位置

我們列舉一個迴文串位置

那麼區間[i,j]除去自迴文剩下的前一塊,有多少個字尾的反串和t的字首匹配,這就是s的這個迴文串的貢獻

s一個區間字尾的反串和t的字首匹配

等價於

s的反串上,對應區間字尾和t的字首匹配

所對應的貢獻就是最長匹配長度

這個可以用exkmp求

列舉迴文串位置是不行的

我們可以先用mamacher求出每個位置的最長迴文半徑

迴文半徑覆蓋的所有位置都有他們對應的最長匹配長度額貢獻

把exkmp求出的extend陣列做字首和,就可以快速求一個s的一個迴文中心對應的所有自迴文串的所有貢獻

#include<bits/stdc++.h>

using namespace std;

#define N 1000004

char s[N],t[N];
char ss[N<<1];

int ls,lt;
int lss;

int extend[N],nxt[N]; 
long long suf[N]; int p[N<<1]; void getnext() { int a=0,p,l,j; nxt[0]=lt; while(a<lt-1 && t[a]==t[a+1]) ++a; nxt[1]=a; a=1; for(int k=2;k<lt;++k) { p=a+nxt[a]-1; l=nxt[k-a]; if(k-1+l>=p) { j=p-k+1>0 ? p-k+1
: 0; while(k+j<lt && t[k+j]==t[j]) ++j; nxt[k]=j; a=k; } else nxt[k]=l; } } void exkmp() { getnext(); int a=0; int minlen=ls<lt ? ls : lt; while(a<minlen && s[a]==t[a]) ++a; extend[0]=a; a=0; int p,l,j; for(int k=1;k<ls;++k) { p=a+extend[a]-1; l=nxt[k-a]; if(k-1+l>=p) { j=p-k+1>0 ? p-k+1 : 0; while(k+j<ls && j<lt && s[k+j]==t[j]) ++j; extend[k]=j; a=k; } else extend[k]=l; } suf[0]=extend[0]; for(int i=1;i<ls;++i) suf[i]=suf[i-1]+extend[i]; } void manacher() { ss[0]='!'; for(int i=0;i<ls;++i) { ss[++lss]='#'; ss[++lss]=s[i]; } ss[++lss]='#'; ss[lss+1]='@'; int id=0,pos=0,x=0; for(int i=1;i<=lss;++i) { if(pos>i) x=min(p[id*2-i],pos-i); else x=1; while(ss[i-x]==ss[i+x]) ++x; if(i+x>pos) pos=i+x,id=i; p[i]=x; } } void solve() { long long ans=0; int r,ql,qr; for(int i=2;i<=lss-2;++i) { r=p[i]-1>>1; if((i&1) && !r) continue; if(i&1) { ql=i/2+1; qr=ql+r-1; } else { ql=i/2; qr=ql+r; } if(qr==ls) --qr; ans+=suf[qr]-suf[ql-1]; } printf("%lld",ans); } int main() { scanf("%s%s",s,t); ls=strlen(s); lt=strlen(t); reverse(s,s+ls); exkmp(); manacher(); solve(); }
作者:xxy 出處:http://www.cnblogs.com/TheRoadToTheGold/ 本文版權歸作者和部落格園共有,轉載請用連結,請勿原文轉載,Thanks♪(・ω・)ノ。