官方题解不是很详细

首先有一个结论:若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. sublime Text 块编辑方法

    比如我们要把SQL语句中的多表查询结果封装成pojo SQL: SELECT a.id, a.title, a.sell_point, a.price, a.image, b.`name` categ ...

  2. HDU 5641

    King's Phone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  3. Java日期时间实用工具类

    Java日期时间实用工具类 1.Date (java.util.Date)    Date();        以当前时间构造一个Date对象    Date(long);        构造函数   ...

  4. C#学习之自定义数组及其排序

    在C#中对数组的定义比较灵活.这里着重说一下自定义数组和Array类的排序. 在Array类中通过属性Length就可以获取整个数组中数据的数量,可以通过foreach迭代数组. 使用Rank属性可以 ...

  5. Ubuntu14.04-Python2.7-Virtualenv-Django1.9-MySQL完整环境配置

    一.安装Ubuntu14.04LTS 1.下载了ubuntu14.04后用ultraISO写到硬盘镜像(U盘) 开机启动项改成U盘在前,安装. 清空分区,重新分配. /最少10G,我放了100G. 物 ...

  6. java删除目录下符合条件的文件

    自己做的一个小程序,目的是:删除某个目录下所有的文件大小为0的文件.同理其他的条件也可以,只需修改delFile()方法中的判断条件即可. 下面是代码,有需要的同学可以参考下,如有错误请指出,不胜感激 ...

  7. 字符串类dp的题目总结

    熟练掌握回文串吧,大致有dp或者模拟类的吧 ①dp+预处理,懂得如何枚举回文串(一) ②dp匹配类型的题目(二) ③dp+预处理 子串类型 (三) ④字符串的组合数(四) 一:划分成回文串 UVA11 ...

  8. J2EE保留小数问题

    如果在前台页面,可以直接使用js的toFixed() 方法.number.toFixed(x)  可把 Number 四舍五入为指定小数位数的数字.参数x :必需.规定小数的位数,是 0 ~ 20 之 ...

  9. Could not load file or assembly 'Microsoft.ReportViewer.Common, Version=11.0.0.0 异常处理

    在本机开发asp.net .rdlc报表后,部署到本地没有问题. 当把网站发布后部署在IIS上,新电脑上(只安装了.net framwork4.5),提示如下错误: “Could not load f ...

  10. performSelector支持多参数

    默认的performSelector支持最多传递两个参数,要想传递超过两个的参数,需要使用NSInvocation来模拟performSelector的行为,如下: - (id)performSele ...