官方题解不是很详细

首先有一个结论:若A=pa+sa B=pb+sb

A、B串循环同构,则可以构造一个可行方案(pa,sb) (sa,pb)中有一个是最长匹配,这个不难用反证法证明。

对于s1,s2串,我们穷举s1的每一个后缀i,设s1[i..i+len-1]=s2[0..len-1] len是最长匹配

那么不难得到,如果存在k使得k<=len且s1[0..i-1]=s2[k..k+i-1]

那么,两串前缀s1[0..i+k-1]为循环同构

因此我们预处理w[i][j]表示s1[0..i]=s2[j..j+i]是否相等,w数组我们可用bitset压位存储

求出这个数组我们只需要建立后缀数组然后顺着height[]找即可

下面我们在将变量代换,前缀p=i+k-1循环同构的条件为i-1<=p<=len+i-1且w[i-1][p]为1

这个条件我们在压位的情况下可以用位运算处理

问题得解

 #include<bits/stdc++.h>

 using namespace std;
bitset<> w[],ans,pre[],tmp;
char s2[],s1[];
int d[],lg[],h[],s[],rk[],sa[],x[],y[],a[];
int f[][],n;
pair<int,int> q[];
bool cmp(int a,int b,int j)
{
if (y[a]==y[b])
{
if (a+j<=n&&b+j<=n) return y[a+j]!=y[b+j];
else if (a+j>n&&b+j>n) return ;
else return ;
}
return y[a]!=y[b];
} void suffix()
{
int m=;
memset(s,,sizeof(s));
for (int i=; i<=n; i++) s[a[i]]++;
for (int i=; i<=m; i++) s[i]+=s[i-];
for (int i=n; i; i--) sa[s[a[i]]--]=i;
int p=; rk[sa[]]=;
for (int i=; i<=n; i++)
{
if (a[sa[i]]!=a[sa[i-]]) ++p;
rk[sa[i]]=p;
}
int j=; m=p;
while (m<n)
{
memcpy(y,rk,sizeof(rk));
memset(s,,sizeof(s));
p=;
for (int i=n-j+; i<=n; i++) x[++p]=i;
for (int i=; i<=n; i++)
if (sa[i]>j) x[++p]=sa[i]-j;
for (int i=; i<=n; i++) s[rk[i]=y[x[i]]]++;
for (int i=; i<=m; i++) s[i]+=s[i-];
for (int i=n; i; i--) sa[s[rk[i]]--]=x[i];
rk[sa[]]=; p=;
for (int i=; i<=n; i++)
{
if (cmp(sa[i],sa[i-],j)) ++p;
rk[sa[i]]=p;
}
m=p; j<<=;
}
p=; h[]=;
for (int i=; i<=n; i++)
{
if (rk[i]==) continue;
int j=sa[rk[i]-];
while (i+p<=n&&j+p<=n&&a[i+p]==a[j+p]) ++p;
h[rk[i]]=p;
if (p) p--;
}
} int ask(int x,int y)
{
int k=lg[y-x+];
return min(f[x][k],f[y-d[k]+][k]);
} void rmq()
{
for (int i=; i<=n; i++)
f[i][]=h[i];
for (int j=; j<=lg[n]; j++)
{
for (int i=; i<=n; i++)
if (i+d[j]-<=n) f[i][j]=min(f[i][j-],f[i+d[j-]][j-]);
else break;
}
} int main()
{
// freopen("1002.in","r",stdin);
d[]=; lg[]=;
for (int i=; i<=; i++)
{
d[i]=d[i-]*;
for (int j=d[i-]; j<=min(,d[i]-); j++) lg[j]=i-;
}
pre[][]=;
for (int i=; i<; i++)
{
pre[i]=pre[i-];
pre[i][i]=;
}
while (scanf("%s%s",s1,s2)!=EOF)
{
int l=strlen(s1);
n=;
for (int i=; i<l; i++) a[++n]=s1[i]-'a'+;
a[++n]=;
for (int i=; i<l; i++) a[++n]=s2[i]-'a'+;
a[n+]=;
suffix(); rmq();
for (int i=; i<l; i++) w[i].reset();
int len=n,m=;
for (int i=rk[]+; i<=n; i++)
{
len=min(len,h[i]);
if (!len) break;
else if (sa[i]>l+) q[++m]=make_pair(len-,sa[i]-l-);
}
len=h[rk[]];
for (int i=rk[]-; i; i--)
{
if (!len) break;
else if (sa[i]>l+) q[++m]=make_pair(len-,sa[i]-l-);
len=min(len,h[i]);
}
sort(q+,q++m);
tmp.reset(); int j=m;
for (int i=l-; i>=; i--)
{
while (j&&q[j].first==i) tmp[q[j--].second]=;
w[i]=tmp;
}
ans.reset();
for (int i=; i<l; i++)
{
int x=rk[i+],y=rk[l+];
if (x>y) swap(x,y);
len=ask(x+,y);
if (len)
{
if (i) ans|=(pre[i-]^pre[i+len-])&(w[i-]<<(i-));
else ans|=pre[len-];
}
}
for (int i=; i<l; i++)
if (ans[i]) printf(""); else printf("");
puts("");
}
}

hdu5782的更多相关文章

随机推荐

  1. How to speed up insertion performance in PostgreSQL

    Disable any triggers on the table Drop indexes before starting the import, re-create them afterwards ...

  2. G. Trace ACM-ICPC 2018 徐州赛区网络预赛 线段树写法

    There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xx , yy  ...

  3. ZOJ 2532 Internship 求隔边

    Internship Time Limit: 5 Seconds      Memory Limit: 32768 KB CIA headquarter collects data from acro ...

  4. FreeRTOS ------ 栈、堆、任务栈

    1.任务的栈资源(创建任务分配的资源,单位是4字节)来自 configTOTAL_HEAP_SIZE 定义的堆,如果任务栈总量超过 configTOTAL_HEAP_SIZE,任务创建失败: 2.如果 ...

  5. Nginx的启动、停止、平滑重启

    转载自:http://www.xj123.info/2572.html 启动Nginx /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/ngi ...

  6. [ASP.NET]从ASP.NET Postback机制,到POST/GET方法

    写这篇博客的起源来自于自己最近在学习ASP.NET时对于 PostBack机制的困惑.因为自己在解决困惑地同时,会不断产生新的疑问,因此博客最后深入到了http 包的格式和Internet所使用的TC ...

  7. AngularJS学习——价格计算器

    利用AngularJs实现价格计算器,总价满100免运费.(熟悉$watch的使用)

  8. [洛谷P4768] [NOI2018]归程 (kruskal重构树模板讲解)

    洛谷题目链接:[NOI2018]归程 因为题面复制过来有点炸格式,所以要看题目就点一下链接吧\(qwq\) 题意: 在一张无向图上,每一条边都有一个长度和海拔高度,小\(Y\)的家在\(1\)节点,并 ...

  9. 嵌入式Nosql数据库——LiteDB

    LiteDB是一个开源的 .NET 开发的小型快速轻量级的 NoSQL 嵌入式数据库,特性: 无服务器的 NoSQL 文档存储,数据存储在单一文件中类似 MongoDb 的简单 API100% C# ...

  10. Item 2---遇到构造器具有多个参数时,要考虑用构建器;Builder模式

    问题,面对这种一个构造器具备多个参数的问题,现有的做法是使用重叠构造器的方式,该方式存在的问题: public class NutritionFacts { private final int ser ...