spoj1811  给两个长度小于100000的字符串 A 和 B,求出他们的最长公共连续子串。

先将串 A 构造为 SAM ,然后用 B 按如下规则去跑自动机。
用一个变量 lcs 记录当前的最长公共子串,初始化为0。
设当前状态结点为 p,要匹配的字符为 c,若 go[c] 中有边,说明能够转移状态,则转移并 lcs++;
若不能转移则将状态移动到 p 的 par ,如果仍然不能转移则重复该过程直到 p 回到根节点,并将 lcs 置为 0;
如果在上一个过程中进入了能够转移的状态,则设 lcs 为当前状态的 val。
为什么失配后要移向 par 呢?因为在状态 p 上失配说明该状态的 [min,max] 所表示字符串都不是 B 中的子串,但是比它们短的后缀仍有可能是 B 的子串,而 par 指针恰好指向了该状态的后缀。

spoj1812  要求多个串的最长公共子串,n<=100000,10个串。

本来想用广义sam,然后对每个点位压10位表示它能到哪些串,最后dfs一遍。
20*10^5=10^6个点,时间压得很紧直接超时。

参照上题做法,就把一个串A放进去,nlcs[x]维护当前串与A在自动机的x节点匹配的最大长度,lcs[x]维护前i个串。做完一个串后for一遍,x没有走到过的点lcs[x]=0,其余的lcs[x]=minn(lcs[x],nlcs[x]);

spoj1811

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std; const int N=*;
char a[N],b[N];
int al,bl,tot,last,son[N][],step[N],pre[N]; int maxx(int x,int y){return x>y ? x:y;} int add_node(int x)
{
step[++tot]=x;
return tot;
} void extend(int ch)
{
int p=last,np=add_node(step[p]+);
while(p && !son[p][ch]) son[p][ch]=np,p=pre[p];
if(!p) pre[np]=;
else
{
int q=son[p][ch];
if(step[q]==step[p]+) pre[np]=q;
else
{
int nq=add_node(step[p]+);
memcpy(son[nq],son[q],sizeof(son[q]));
pre[nq]=pre[q];
pre[q]=pre[np]=nq;
while(son[p][ch]==q) son[p][ch]=nq,p=pre[p];
}
}
last=np;
} int main()
{
freopen("a.in","r",stdin);
// freopen("me.out","w",stdout);
memset(son,,sizeof(son));
memset(pre,,sizeof(pre));
memset(step,,sizeof(step));
tot=;add_node();last=;
scanf("%s%s",a+,b+);
al=strlen(a+),bl=strlen(b+);
for(int i=;i<=al;i++) extend(a[i]-'a'+);
int ch,x=,ans=,len=;
for(int i=;i<=bl;i++)
{
ch=b[i]-'a'+;
while(x && !son[x][ch]) x=pre[x],len=step[x];
if(x==) x=;
if(son[x][ch]) x=son[x][ch],len++; ans=maxx(ans,len);
}
printf("%d\n",ans);
return ;
}

spoj1812

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std; const int N=*;
char s[][N];
int n,tot,last,son[N][],step[N],pre[N],lcs[N],nlcs[N],l[];
bool vis[N];
struct node{
int x,y,next;
}a[*N]; int maxx(int x,int y){return x>y ? x:y;}
int minn(int x,int y){return x<y ? x:y;} int add_node(int x)
{
step[++tot]=x;lcs[tot]=x;
return tot;
} void extend(int ch)
{
int p=last,np=add_node(step[p]+);
while(p && !son[p][ch]) son[p][ch]=np,p=pre[p];
if(!p) pre[np]=;
else
{
int q=son[p][ch];
if(step[q]==step[p]+) pre[np]=q;
else
{
int nq=add_node(step[p]+);
memcpy(son[nq],son[q],sizeof(son[q]));
pre[nq]=pre[q];
pre[q]=pre[np]=nq;
while(son[p][ch]==q) son[p][ch]=nq,p=pre[p];
}
}
last=np;
} void solve(int id)
{
memset(nlcs,,sizeof(nlcs));
memset(vis,,sizeof(vis));
int x=,len=,ch;
for(int i=;i<=l[id];i++)
{
ch=s[id][i]-'a'+;
while(x && !son[x][ch])
{
x=pre[x],len=step[x],vis[x]=;
nlcs[x]=maxx(nlcs[x],len);
}
if(x==) x=,vis[]=;
if(son[x][ch]) x=son[x][ch],vis[x]=,len++;
nlcs[x]=maxx(nlcs[x],len);
}
for(int i=;i<=tot;i++)
if(!vis[i]) lcs[i]=;
else lcs[i]=minn(lcs[i],nlcs[i]);
} int main()
{
freopen("a.in","r",stdin);
// freopen("me.out","w",stdout);
memset(son,,sizeof(son));
memset(pre,,sizeof(pre));
memset(step,,sizeof(step));
tot=;add_node();last=;n=;
while(scanf("%s",s[++n]+)!=EOF)
{
l[n]=strlen(s[n]+);
}n--;
for(int i=;i<=l[];i++) extend(s[][i]-'a'+);
for(int i=;i<=n;i++) solve(i);
int ans=;
for(int i=;i<=tot;i++) ans=maxx(ans,lcs[i]);
printf("%d\n",ans);
return ;
}

【spoj1811 & spoj1812 - LCS1 & LCS2】sam的更多相关文章

  1. 【UOJ131/NOI2015D2T2-品酒大会】sam求后缀树

    题目链接:http://uoj.ac/problem/131 题意:给出一个字符串,第i个字符对应的值为a[i], 对于i∈[0,n),求最长公共前缀大于等于i的字串对个数,并求这些字符串对开头对应值 ...

  2. SPOJ1811 && SPOJ1812

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

  3. 【疯狂造轮子-iOS】JSON转Model系列之二

    [疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...

  4. 【疯狂造轮子-iOS】JSON转Model系列之一

    [疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...

  5. 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付

    前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...

  6. 【AutoMapper官方文档】DTO与Domin Model相互转换(上)

    写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...

  7. 【开源】分享2011-2015年全国城市历史天气数据库【Sqlite+C#访问程序】

    由于个人研究需要,需要采集天气历史数据,前一篇文章:C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子),介绍了基本的采集思路和核心代码,经过1个星期的采集,历史数据库 ...

  8. 【原创分享·微信支付】C# MVC 微信支付教程系列之现金红包

            微信支付教程系列之现金红包           最近最弄这个微信支付的功能,然后扫码.公众号支付,这些都做了,闲着无聊,就看了看微信支付的其他功能,发现还有一个叫“现金红包”的玩意,想 ...

  9. 【原创分享·微信支付】 C# MVC 微信支付教程系列之扫码支付

    微信支付教程系列之扫码支付                  今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添 ...

随机推荐

  1. 高德API+.NET解决租房问题(新增诚信房源)

    作者:李国宝链接:https://zhuanlan.zhihu.com/p/22105008(欢迎点赞)来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 之前有小伙伴反应 ...

  2. LARK BOARD开发板入门学习-第2篇

    1. 本次主要研究下HDMI接口,使用芯片是CH7033,这个芯片可以接VGA和HDMI两种接口,和FPGA的接口是地址数据总线 2. 值得注意的地方,下图的D1,双二极管BAT54S在电路中一般用于 ...

  3. npx 命令介绍

    这个是在 npmv5.2.0引入的一条命令(查看),引入这个命令的目的是为了提升开发者使用包内提供的命令行工具的体验. 为什么引入这个命令 举个例子,我们开发中要运行 parcel 命令来打包:par ...

  4. spring mvc:实现给Controller函数传入list<pojo>参数

    [1]前端js调用示例: ...insertStatisData?statisDatas=[{'cid':'2','devId':'9003','deviceName':'测试名','endTime' ...

  5. HDU 4571 Travel in time(最短路径+DP)(2013 ACM-ICPC长沙赛区全国邀请赛)

    Problem Description Bob gets tired of playing games, leaves Alice, and travels to Changsha alone. Yu ...

  6. week12第二轮迭代任务分配forZ.XML

    Z.XML第二轮迭代任务初步分配新鲜出炉,请关注! 以上便是任务分配列表,队员们会按照进度每天更改任务进度 当然,根据敏捷开发的方法,我们将在开发过程中根据情况迅速调整任务分配,以适应当时问题. Z- ...

  7. 【iOS开发】动态添加子视图 UIView 的正确方法

    很多时候哥比较喜欢用代码添加视图,特别是要同时加很多UIView时,而且跟 xib 比起来代码更容易管理,在多人的项目中代码不容易 conflict. 但小牛哥最近发现很多新人都不太清楚正确的使用方法 ...

  8. 【历史】- 一段关于 Unix、Linux 和 Windows 的暗黑史

    “SCO在言语上变得越来越好斗,而且还拒绝展示有关诉讼的任何证据,一切都似乎在表明,SCO只不过是在那里拉虎皮做大旗地狂言乱语.但是,微软决不会轻易放弃这么可以一个利用这些狂言乱语的好机会.”2003 ...

  9. 如何让旧浏览器支持HTML5新标签

    HTML5出现也不短了,很多网站的页面都进行了改版,为了降低代码量(不需要起太多的类名),提升加载速度,提高标签的语义性,因此,在网页中大量使用了section,article,header等HTML ...

  10. zTree基本功能[core]

    zTree 是一个依靠jQuery实现的多功能"树插件".优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. zTree v3.0 将核心代码按照功能进行了分割,不需 ...