【spoj1811 & spoj1812 - LCS1 & LCS2】sam
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的更多相关文章
- 【UOJ131/NOI2015D2T2-品酒大会】sam求后缀树
题目链接:http://uoj.ac/problem/131 题意:给出一个字符串,第i个字符对应的值为a[i], 对于i∈[0,n),求最长公共前缀大于等于i的字串对个数,并求这些字符串对开头对应值 ...
- SPOJ1811 && SPOJ1812
SPOJ1811 && SPOJ1812 LCS && LCS2 非常神奇的两道题... 题目大意: 给定n个字符串,求最长公共子串 做法1: 后缀数组: 把字符串连起 ...
- 【疯狂造轮子-iOS】JSON转Model系列之二
[疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...
- 【疯狂造轮子-iOS】JSON转Model系列之一
[疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...
- 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付
前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(上)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- 【开源】分享2011-2015年全国城市历史天气数据库【Sqlite+C#访问程序】
由于个人研究需要,需要采集天气历史数据,前一篇文章:C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子),介绍了基本的采集思路和核心代码,经过1个星期的采集,历史数据库 ...
- 【原创分享·微信支付】C# MVC 微信支付教程系列之现金红包
微信支付教程系列之现金红包 最近最弄这个微信支付的功能,然后扫码.公众号支付,这些都做了,闲着无聊,就看了看微信支付的其他功能,发现还有一个叫“现金红包”的玩意,想 ...
- 【原创分享·微信支付】 C# MVC 微信支付教程系列之扫码支付
微信支付教程系列之扫码支付 今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添 ...
随机推荐
- ES5新增数组方法(2):map
通过指定函数处理数组的每个元素,并返回处理后的数组. 1.计算数组中每个元素的平方 let arr = [1, 2, 3, 4, 5, 6]; let newArr = arr.map(item =& ...
- Qt 隐藏标题栏可移动升级版
在最出的时候,在Qt程序隐藏标题栏的情况下,实现界面可拖拽移动,是鼠标在在程序界面的任意位置都可以,现在这个版本是需要鼠标在程序界面的特定位置开可以 上代码 static QPoint last(0, ...
- No resources found. Error from server (NotAcceptable): unknown (get pods)
问题:正确安装kubectl后,可查询到当前使用集群服务,也可切换不同的集群,但无法获取当前运行的pods的信息与所有的service,具体表现为 $ kubectl get po -nwx No r ...
- css制作环形文本
css制作环形文本 在项目开发中,我们可能会遇到环形文本的需求,这个时候,怎样在代码以通俗易懂的前提下实现我们需要的效果呢?可能你会想到用一个一个的span元素计算出旋转的角度然后拼接起来,这个方案不 ...
- 小C的记事本(栈记录字符串)
链接:https://www.nowcoder.com/acm/contest/122/D来源:牛客网 题目描述 小C最近学会了java小程序的开发,他很开心,于是想做一个简单的记事本程序练练手. 他 ...
- 关于php网络爬虫phpspider
前几天,被老板拉去说要我去抓取大众点评某家店的数据,当然被我义正言辞的拒绝了,理由是我不会...但我的反抗并没有什么卵用,所以还是乖乖去查资料,因为我是从事php工作的,首先找的就是php的网络爬虫源 ...
- 通过NTP(Network Time Protocal)协议进行时间同步
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAwUAAAKOCAYAAAD3ZbXWAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjw
- asp.net中的cookie
一.cookie导读,理解什么是cookie 1.什么是cookie:cookie是一种能够让网站服务器把少量数据(4kb左右)存储到客户端的硬盘或内存.并且读可以取出来的一种技术. 2.当你浏览某网 ...
- 【转】深入理解Java中的String
原文链接:http://www.cnblogs.com/xiaoxi/p/6036701.html 一.String类 想要了解一个类,最好的办法就是看这个类的实现源代码,来看一下String类的源码 ...
- BZOJ4597 SHOI2016随机序列(线段树)
先考虑题目所说的太简单了的问题.注意到只要把加减号相取反,就可以得到一对除了第一项都互相抵消的式子.于是得到答案即为Σf(i)g(i),其中f(i)为前缀积,g(i)为第i个数前面所有符号均填乘号,第 ...