JSOI 2016 扭動的字串

2022-08-18 22:33:25 字數 1330 閱讀 8323

給出兩個長度為\(n\)的字串\(a,b\)

\(s(i,j,k)\)表示把\(a\)中的\([i,j]\)和\(b\)中的\([j,k]\)拼接起來的字串

問所有回文的\(s(i,j,k)\)或者\(a,b\)中的回文子串的最長長度

列舉回文串的中心。

可以發現,如果能在當前字串內擴充套件就盡量擴充套件,不能擴充套件了再嘗試和另乙個字串匹配。

對於前者,使用\(manacher\)演算法

對於後者,二分乙個長度,用\(hash\)判斷能否匹配。

以上

#include#define pii pair#define mkp(x,y) make_pair(x,y)

using namespace std;

const int sz=2e5+7;

const int p1=998244353;

const int p2=1e8+7;

const int q1=5271314;

const int q2=2374899;

int n,m;

int ans;

int p[2][sz];

char s[2][sz];

char ss[2][sz<<1];

int w[2][sz];

int pre[2][2][sz],suf[2][2][sz];//字串,雜湊,位置

void init(int tp)

}void hash(int tp)

hs0=hs1=0;

for(int i=n;i>=1;i--)

}pii gs(int tp,int st,int l)

pii gn(int tp,int st,int l)

int main()

m=2*n+1;

w[0][0]=w[1][0]=1;

for(int i=1;i<=n;i++)

init(0),init(1);

hash(0),hash(1);

int l,r,sl,sr,len,l,r,mid;

for(int i=2;i>1;

if(gs(0,sl,mid)==gn(1,sr,mid)) l=mid;

else r=mid-1;

} ans=max(ans,len+2*l);

} for(int i=2;i>1;

if(gs(0,sl,mid)==gn(1,sr,mid)) l=mid;

else r=mid-1;

} ans=max(ans,len+2*l);

} printf("%d\n",ans);

}

JSOI2016 扭動的回文串

description jyy有兩個長度均為n的字串a和b。乙個 扭動字串s i,j,k 由a中的第i個字元到第j個字元組成的子串 與b中的第j個字元到第k個字元組成的子串拼接而成。比如,若a xyz b uvw 則扭動字串s 1,2,3 xyvw jyy定義乙個 扭動的回文串 為如下情況中的乙個 ...

JSOI2016 扭動的回文串

可以發現最後的答案一定長成 a 串和 b 串的一對對稱的子串 長度可以為 0 然後中間夾著 a 串或者 b 串中的乙個回文串 長度可以為 0 對於每乙個中心點,對應的最大的答案中間所夾的那個回文串一定是以這個中心點為對稱中心的最長回文串 那麼就從以這個中心點為對稱中心的最長回文串的兩邊開始找那個 a...

JSOI2016 扭動的回文串

清新結論配上巨大碼量的雜湊解法 第一種情況和第二種情況很容易解決,可以直接求乙個正向雜湊值在求乙個反轉後的雜湊值,然後列舉回文中心,二分擴充套件了多少即可。思考扭動的回文串應該滿足那些特性,首先,一定是一段滿足情況 1 或情況 2 的子串 s 然後左邊新增了一些,右邊新增了一些,很明顯,無論 s 是...