题意是求两个字符串的lcs,两个串都只包含小写字母。

本题既可以用后缀自动机,又可以用后缀数组。

对于后缀自动机,就是一道模板题,直接对于一个字符串建后缀自动机再用另一个串查询就行。

对于后缀数组,其实也是一道模板题,但不是后缀数组的模板,而是用后缀数组求同一字符串的两个后缀的最长公共前缀的模板。

用h(x)表示排序前在第x位的后缀s1与排序后排在s1前一位的s2(记为prev(x))的最长公共前缀。

这样就会发现这些性质:

1.想要求出排序前位于k1,k2的后缀的最长公共前缀,只需要(用后缀数组)找出它们在排序后的位置,再求区间最值就可以。

2.对于排序前位于k的后缀s,它和所有排序后在它前面后缀的最长公共前缀不会超过h(k)。

根据性质2,会发现可以将两个用一个奇怪的字符连成一个大串,再对这个大串求后缀数组。这样,对于所有满足x与prev(x)在奇怪的字符异侧的h(x)求最大值就可以了。

那么问题又来了,如何快速求h(x)?

直接比较显然是不行的。经过一番并不对劲的考虑,发现h(x)>=h(x-1)-1。这是因为h(x-1)表示第x-1位的后缀和第prev(x-1)位的后缀的最长公共前缀,而第x位的后缀相当于是将第x-1位后缀最前面的字符去掉后形成的。那么,将第prev(x-1)位的后缀最前面的字符去掉,得到的字符串也是后缀之一(可能为空),而且它与第x位的后缀的最长公共前缀是h(x-1)-1。也就是说,第x位的后缀在排序后前面存在一个后缀与它的最长公共前缀是h(x-1)-1。根据性质2,就可以得出h(x)>=h(x-1)-1了。这样就能大大地减少了复杂度。

感觉这题还是用后缀自动机更方便。

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define maxn 500010
using namespace std;
inline int read()
{
int xx=,ff=;
char ch=getchar();
while(isdigit(ch)==&&ch!='-')ch=getchar();
if(ch=='-')ff=-,ch=getchar();
while(isdigit(ch))xx=xx*+ch-'',ch=getchar();
return xx*ff;
}
void write(int x)
{
int ff=;char ch[];
if(x<)
{
x=-x;
putchar('-');
}
while(x)ch[++ff]=(x%)+'',x/=;
if(ff==)putchar('');
while(ff)putchar(ch[ff--]);
putchar(' ');
}
int sa[maxn],ord[maxn],x[maxn],n,m=;
int y[maxn],c[maxn],h[maxn];
char s[maxn];
void get_sa()
{
memset(x,,sizeof(x));
memset(y,,sizeof(y));
memset(c,,sizeof(c));
for (int i=;i<n;i++) c[x[i]=s[i]]++;
for (int i=;i<m;i++) c[i]+=c[i-];
for (int i=n-;i>=;i--) sa[--c[x[i]]]=i;
for (int k=;k<=n;k<<=)
{
int p = ;
for (int i=n-k;i<n;i++) y[p++] = i;
for (int i=;i<n;i++) if (sa[i] >= k) y[p++] = sa[i] - k;
for (int i=;i<m;i++) c[i] = ;
for (int i=;i<n;i++) c[x[y[i]]]++;
for (int i=;i<m;i++) c[i] += c[i-];
for (int i=n-;i>=;i--) sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = ;
x[sa[]] = ;
for (int i=;i<n;i++)
x[sa[i]]= (y[sa[i-]]==y[sa[i]]&&y[sa[i-]+k]==y[sa[i]+k])?p-:p++;
if (p>=n) break;
m=p;
}
}
void getheight()
{
int i,j,k=;
memset(h,,sizeof(h));
for(i=;i<n;i++) ord[sa[i]]=i;
for(i=;i<n;i++)
{
if(k) k--;
if(ord[i]==)continue;
j=sa[ord[i]-];
while(s[i+k]==s[j+k]) k++;
h[i]=k;
}
}
int main()
{
char s2[maxn];
scanf("%s",s);
int split=strlen(s);
scanf("%s",s2);
strcat(s,"A");
strcat(s,s2);
n=strlen(s);
get_sa();
getheight();
int maxx=;
for(int i=;i<n;i++)
{
if((sa[i]>split&&sa[i-]<split)||(sa[i-]>split&&sa[i]<split))
{
maxx=max(maxx,h[sa[i]]);
}
}
write(maxx);
return ;
}

SA

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 250010
using namespace std;
int ans,len,p;
int read()
{
int f=,x=;char ch=getchar();
while(isdigit(ch)== && ch!='-')ch=getchar();
if(ch=='-')f=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();
return x*f;
}
void write(int x)
{
int ff=;char ch[];
while(x)ch[++ff]=(x%)+'',x/=;
if(ff==)putchar('');
while(ff)putchar(ch[ff--]);
putchar(' ');
}
typedef struct node
{
int to[],dis,fa;
}spot;
struct SAM
{
spot x[maxn*];
int cnt,rt,lst;
char s[maxn];
void start()
{
lst=rt=++cnt;
scanf("%s",s+);
int ls=strlen(s+);
for(int i=;i<=ls;i++)
extend(i);
}
void extend(int pos)
{
int val=s[pos]-'a',p=lst,np=++cnt;
lst=np,x[np].dis=pos;
for(;p&&x[p].to[val]==;p=x[p].fa)x[p].to[val]=np;
if(p==)x[np].fa=rt;
else
{
int q=x[p].to[val];
if(x[q].dis==x[p].dis+)x[np].fa=q;
else
{
int nq=++cnt;
x[nq].dis=x[p].dis+;
memcpy(x[nq].to,x[q].to,sizeof(x[q].to));
x[nq].fa=x[q].fa,x[np].fa=x[q].fa=nq;
for(;x[p].to[val]==q;p=x[p].fa)x[p].to[val]=nq;
}
}
}
}t;
int main()
{
char s2[maxn];
t.start();
scanf("%s",s2+);
int ls2=strlen(s2+);
p=t.rt;
for(int i=;i<=ls2;i++)
{
int val=s2[i]-'a';
if(t.x[p].to[val])len++,p=t.x[p].to[val];
else
{
while(p&&t.x[p].to[val]==)p=t.x[p].fa;
if(p==)p=t.rt,len=;
else len=t.x[p].dis+,p=t.x[p].to[val];
}
ans=max(ans,len);
}
write(ans);
return ;
}

SAM

并不对劲的spoj1811的更多相关文章

  1. 并不对劲的spoj1812

    题意是求多个串的lcs. 这也是道后缀自动机的模板题.对于任意一个字符串建后缀自动机,用其他串查询就行.对于后缀自动机的每个状态要额外记匹配到当前状态的最大长度. 和spoj1811的区别在于这道题不 ...

  2. SPOJ1811 && SPOJ1812

    SPOJ1811 && SPOJ1812 LCS && LCS2 非常神奇的两道题... 题目大意: 给定n个字符串,求最长公共子串 做法1: 后缀数组: 把字符串连起 ...

  3. 【spoj1811 & spoj1812 - LCS1 & LCS2】sam

    spoj1811  给两个长度小于100000的字符串 A 和 B,求出他们的最长公共连续子串. 先将串 A 构造为 SAM ,然后用 B 按如下规则去跑自动机.用一个变量 lcs 记录当前的最长公共 ...

  4. 并不对劲的BJOI2019

    一些感想 现实并非游戏,并不支持反复刷关 猎人和防御工事一起被老山龙摧毁了: 猎人惨死雨中,结云村永无放晴之日: 猎人被狂龙病毒侵蚀,天空山上黑蚀龙泛滥. 好像这才是怪物猎人系列的真实结局呢 day ...

  5. 并不对劲的uoj276. [清华集训2016]汽水

    想要很对劲的讲解,请点击这里 题目大意 有一棵\(n\)(\(n\leq 50000\))个节点的树,有边权 求一条路径使该路径的边权平均值最接近给出的一个数\(k\) 输出边权平均值下取整的整数部分 ...

  6. 并不对劲的DFT

    FFT是一个很多人选择背诵全文的算法. #include<algorithm> #include<cmath> #include<complex> #include ...

  7. 并不对劲的字符串专题(三):Trie树

    据说这些并不对劲的内容是<信息学奥赛一本通提高篇>的配套练习. 并不会讲Trie树. 1.poj1056-> 模板题. 2.bzoj1212-> 设dp[i]表示T长度为i的前 ...

  8. 并不对劲的字符串专题(二):kmp

    据说这些并不对劲的内容是<信息学奥赛一本通提高篇>的配套练习. 先感叹一句<信息学奥赛一本通提高篇>上对kmp的解释和matrix67的博客相似度99%(还抄错了),莫非mat ...

  9. 并不对劲的bzoj1861: [Zjoi2006]Book 书架

    传送门-> 这题的正确做法是splay维护这摞书. 但是并不对劲的人选择了暴力(皮这一下很开心). #include<algorithm> #include<cmath> ...

随机推荐

  1. 常用的四种设计模式 PHP代码

    // 工厂模式 interface Iuser { public function getUserName(); } class UserFactory { static public functio ...

  2. sqlserver同一个局域网内,把服务器数据库备份到客户端

    1.客户端主机创建网络共享文件夹 2.远程服务器运行: EXEC sp_configure 'show advanced options', 1;-- 允许配置高级选项--配置选项'show adva ...

  3. Quartz --quartz.properties

    quartz.properties 如果项目中没有该配置文件,则会去jar包中读取自带配置文件 默认的配置如下 # Default Properties file for use by StdSche ...

  4. Eclipse Myeclipse 设定文件的默认打开方式

    Eclipse Myeclipse 设定文件的默认打开方式   菜单:Window -> Preferences -> General -> Editors -> File A ...

  5. github some rank

    github some rank http://githubrank.com/

  6. MTK平台如何定位显示花屏和界面错乱等绘制异常的问题?

    [DESCRIPTION] 在测试手机各项功能过程中,经常会遇到概率性复现“屏幕画花了,界面画错乱了等绘制异常问题”,而且概率还非常小: 这类问题请不要直接提交eService,而是先请测试人员及工程 ...

  7. Frequent values(poj 3368)

    题意:给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之间连续出现次数最多的次数. 代码: /* rmq算法 当询问到x,y时,设在x之后并且与a[x]相同的最后一个数编号为t,那么x到t之 ...

  8. [USACO5.3]巨大的牛棚Big Barn

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

  9. 【Intellij】Intellij Idea 2017创建web项目及tomcat部署实战

    相关软件:Intellij Idea2017.jdk16.tomcat7 Intellij Idea直接安装(可根据需要选择自己设置的安装目录),jdk使用1.6/1.7/1.8都可以,主要是配置好系 ...

  10. 服务器Centos7.4 下jdk1.8环境配置、mysql环境搭建,mysql找回(重置)密码看这篇就够了

    最近一直帮我的同学搭建自己的服务器,其中涉及到了以下知识点,经过查询博客资料等方式,再加上多重实践,我成功总结出了完整的配置一个简单服务器环境的步骤: (来自 ZYXS 的CSDN 博客 ,全文地址请 ...