你说得对,但是随机化
余于甲辰年,庚午癸亥闻此,叹于随机化之巧,故作此篇,以告其巧之于诸公也。
思路浅析:
题目中所谓的旋转操作的形式化定义:
有一个字符串
在不考虑翻转操作时,题意即是求两个字符串最长循环同构串的长度。
考虑翻转操作翻两次就与原串无异,故只需要考虑将某一个串翻转后和两个都不翻转得到的答案即可。
那么两个循环同构的串有神马性质呢?
考虑我循环位移多次后,将串以现在的
同时,我们发现我们让上文所述的前缀尽可能长是不劣的,考虑我第一个串的那个是第二个串的后缀的前缀向后扩展一位,那么最坏情况下也只是两个串的剩余部分减小一位:
(红色和黄色部分即为最长循环同构串)
可以发现,答案是不会因此变差的。
(下约定
那么一个
枚举两个对应字符相同的
考虑优化,我们知道一个期望时间复杂度
套用上述做法,随机枚举的
参考代码:
#include<bits/stdc++.h>
#define ll long long
#define un unsigned
using namespace std;
const ll MAXN=2;
ll MODs[MAXN+1];
random_device seed;
unsigned ll hss[MAXN+1][3005],hst[MAXN+1][3005];
unsigned ll bs[MAXN+1][200010];
const un ll base=19260817;
char s[3005],t[3005];
ll ans,sst,tst;
un ll get_hss(ll uid,ll l,ll r)
{
return ((hss[uid][r]-hss[uid][l-1]*bs[uid][r-l+1]%MODs[uid])+MODs[uid])%MODs[uid];
}
un ll get_hst(ll uid,ll l,ll r)
{
return ((hst[uid][r]-hst[uid][l-1]*bs[uid][r-l+1]%MODs[uid])+MODs[uid])%MODs[uid];
}
bool check(ll sl,ll sr,ll tl,ll tr)
{
for(ll i=1;i<=MAXN;++i)if(get_hss(i,sl,sr)!=get_hst(i,tl,tr))return 0;
return 1;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
mt19937 rd(seed());
cin>>s>>t;
clock_t st=clock();
ll n=strlen(s),m=strlen(t);
MODs[1]=1000000007ll;MODs[2]=998244353ll;
for(ll k=1;k<=MAXN;++k)
{
bs[k][0]=1;
for(ll i=1;i<=max(n,m);++i)
bs[k][i]=bs[k][i-1]*base%MODs[k];
}
for(ll k=1;k<=MAXN;++k)
for(ll i=1;i<=n;++i)
hss[k][i]=(hss[k][i-1]*base+s[i-1]-'a'+1)%MODs[k];
for(ll k=1;k<=MAXN;++k)
for(ll i=1;i<=m;++i)
hst[k][i]=(hst[k][i-1]*base+t[i-1]-'a'+1)%MODs[k];
while((clock()-st)*1000.00/CLOCKS_PER_SEC<=700)
{
ll sl=rd()%n+1,tl=rd()%m+1;
if(s[sl-1]!=t[tl-1])continue;
ll lenr=1;
for(;sl+lenr<=n&&tl+lenr<=m&&s[sl+lenr-1]==t[tl+lenr-1];++lenr);
while(sl-1>=0&&tl-1>=0&&s[sl-2]==t[tl-2])--sl,--tl,++lenr;
ll maxl=0;
ll sr=sl+lenr-1,tr=tl+lenr-1;
for(ll lenl=1;(sl-lenl)&&tr+lenl<=m&&lenl<=lenr;++lenl)
if(check(sl-lenl,sl-1,tr+1,tr+lenl))
maxl=lenl;
if(maxl+lenr>ans)
{
ans=maxl+lenr;
sst=sl-maxl;tst=tl;
}
maxl=0;
for(ll lenl=1;(tl-lenl)&&sr+lenl<=n&&lenl<=lenr;++lenl)
if(check(sr+1,sr+lenl,tl-lenl,tl-1))
maxl=lenl;
if(maxl+lenr>ans)
{
ans=maxl+lenr;
sst=sl;tst=tl-maxl;
}
}
reverse(t,t+m);
for(ll k=1;k<=MAXN;++k)
for(ll i=1;i<=m;++i)
hst[k][i]=(hst[k][i-1]*base+t[i-1]-'a'+1)%MODs[k];
while((clock()-st)*1000.00/CLOCKS_PER_SEC<=1400)
{
ll sl=rd()%n+1,tl=rd()%m+1;
if(s[sl-1]!=t[tl-1])continue;
ll lenr=1;
for(;sl+lenr<=n&&tl+lenr<=m&&s[sl+lenr-1]==t[tl+lenr-1];++lenr);
while(sl-1>=0&&tl-1>=0&&s[sl-2]==t[tl-2])--sl,--tl,++lenr;
ll maxl=0;
ll sr=sl+lenr-1,tr=tl+lenr-1;
for(ll lenl=1;(sl-lenl)&&tr+lenl<=m&&lenl<=lenr;++lenl)
if(check(sl-lenl,sl-1,tr+1,tr+lenl))
maxl=lenl;
if(maxl+lenr>ans)
{
ans=maxl+lenr;
sst=sl-maxl;tst=m+1-(tl+ans-1);
}
maxl=0;
for(ll lenl=1;(tl-lenl)&&sr+lenl<=n&&lenl<=lenr;++lenl)
if(check(sr+1,sr+lenl,tl-lenl,tl-1))
maxl=lenl;
if(maxl+lenr>ans)
{
ans=maxl+lenr;
sst=sl;tst=m+1-(tl-maxl+ans-1);
}
}
cout<<ans<<'\n'<<sst-1<<' '<<tst-1;
}