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. PRO*C 函数事例 1 -- 数据库连接、事务处理

    1.程序结构        每一个Pro*C程序都包括两部分:(1)应用程序首部:(2)应用程序体        应用程序首部定义了ORACLE数据库的有关变量, 为在C语言中操纵ORACLE数据库做 ...

  2. 使用pyinstaller将Python打包为exe文件

    当我们完成一个Python项目或一个程序时,希望将Python的py文件打包成在Windows系统下直接可以运行的exe程序,那么pyInstaller就是一个很好的选择.pyInstaller可以将 ...

  3. Python request 简单使用

    Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTT ...

  4. 《python核心编程第二版》第2章习题

    2-1 略 2-1 略 2-2 (a)打印 结果是9 (b)9 (c)一样 (d)略 (e)略 2-3 略 2-4 (a) # /usr/bin/pythonraw_input() (b) # /us ...

  5. jmeter☞文件目录(一)

    Jmeter的文件目录如下图: 1.bin:可执行文件目录 a.jmeter.bat:Windows环境下的启动文件 b.jmeter.log:日志文件 c.jmeter.sh:Linux环境下的启动 ...

  6. 05-Mysql数据库----补充内容

    数据库命名规则: 数据库命名规则: 可以由字母.数字.下划线.@.#.$ 区分大小写 唯一性 不能使用关键字如 create select 不能单独使用数字 最长128位 # 基本上跟python或者 ...

  7. python基础篇 07set集合 深浅拷贝

    本节主要内容:1. 基础数据类型补充2. set集合3. 深浅拷⻉ " ".join方法 循环删除列表中的内容:   错误的  原因:在for循环中,循环到第一个,然后删除,删除之 ...

  8. Python 学习笔记之—— PIL 库

    PIL,全称 Python Imaging Library,是 Python 平台一个功能非常强大而且简单易用的图像处理库.但是,由于 PIL 仅支持到Python 2.7,加上年久失修,于是一群志愿 ...

  9. ubuntu中执行truffle build出现问题

    进行build之前,采用默认构建器方式创建客户端,先安装默认构建器: npm install truffle-default-builder --save 然后需要修改truffle.js配置文件如下 ...

  10. 基于Thinkphp5+phpQuery 网络爬虫抓取数据接口,统一输出接口数据api

    TP5_Splider 一个基于Thinkphp5+phpQuery 网络爬虫抓取数据接口 统一输出接口数据api.适合正在学习Vue,AngularJs框架学习 开发demo,需要接口并保证接口不跨 ...