经典题目,求两个串的最长公共子串。

是这样来做的。

以第一个串构造SAM,第二个串在自动机上跟新一遍就可以了。

更新的过程是这样的,假设当前到达的状态点为x(初始状态为0点),下一个字符是c,如果当前状态没有c这条边就一直沿着pre指针走,直到找到第一个有c这条边的状态或者确认全部都没有。

更新是这样的,用一个数字保存上一次状态的最大长度tmp,现在到达了一个新的状态了,显然这个状态一定保证在第二个串出现,因为我是从第二个串里面一个一个字符地添加进来的,那么只要保证满足第一个串(即模式串)就可以了。怎么保证呢?只要不大于tmp不大于该状态的step值就可以了。为什么?因为能到达当前状态的话说明是可以存在这个长度的。tmp与step比较并且去较小值。就完成了更新了。

嗯其实还听简单的。

代码君上了:

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 600300
using namespace std; int next[maxn][26],pre[maxn],step[maxn];
int N=0,last=0,n,p,q,np,nq;
char s[maxn]; void insert(int x,int m)
{
p=last,np=++N;
for (int i=0; i<26; i++) next[N][i]=0; pre[N]=0; step[N]=0;
step[np]=m;
for (;p!=-1 && next[p][x]==0; p=pre[p]) next[p][x]=np;
last=np;
if (p==-1) return;
q=next[p][x];
if (step[q]==step[p]+1) { pre[np]=q; return; }
nq=++N;
for (int i=0; i<26; i++) next[N][i]=0; pre[N]=0; step[N]=0;
step[nq]=step[p]+1;
pre[nq]=pre[q];
for (int i=0; i<26; i++) next[nq][i]=next[q][i];//注意指针不能乱。。
pre[np]=pre[q]=nq;
for (;p!=-1 && next[p][x]==q; p=pre[p]) next[p][x]=nq;
} int dfs()
{
int ans=0,tmp=0;
for (int i=1,cur=0; s[i]; i++)
{
int k=s[i]-'a';
while (next[cur][k]==0 && cur!=0) cur=pre[cur];
if (step[cur]<tmp) tmp=step[cur];
cur=next[cur][k];
if (cur) tmp++;
ans=max(ans,tmp);
}
return ans;
} int main()
{
pre[0]=-1;
for (int i=0; i<26; i++) next[0][i]=0; step[0]=0;
scanf("%s",s+1);
for (int i=1; s[i]; i++) insert(s[i]-'a',i);
scanf("%s",s+1);
printf("%d\n",dfs());
return 0;
}

  

SPOJ_LCS的更多相关文章

  1. SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)

    1811. Longest Common Substring Problem code: LCS A string is finite sequence of characters over a no ...

随机推荐

  1. 初窥Linux之我最常用的20条命令

    1.cd命令   这是一个非常基本,也是大家经常需要使用的命令,它用于切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径.如: cd /root/Docements # 切 ...

  2. MySQL数据库常用操作语法

    1. 数据库初始化配置 1.1. 创建数据库 create database apps character set utf8 collate utf8_bin;创建数据库”app“,指定编码为utf8 ...

  3. 经典笔试题:用C写一个函数测试当前机器大小端模式

    “用C语言写一个函数测试当前机器的大小端模式”是一个经典的笔试题,如下使用两种方式进行解答: 1. 用union来测试机器的大小端 #include <stdio.h> union tes ...

  4. 使用CDN后配置nginx自定义日志获取访问用户的真实IP

    问题描述:         新上线了一个项目,架构如下(简单画的理解就好): 问题是:负载前面加上CDN后负载这里无法获取客户的真实访问IP,只能过去到CDN的IP地址: 问题解决: 修改nginx日 ...

  5. 特效Shader对雾的处理

    RFX4_Particle.shader案例 #ifdef BlendAdd UNITY_APPLY_FOG_COLOR(i.fogCoord, res, half4(0,0,0,0)); #endi ...

  6. 经典的性能优化最佳实践 web性能权威指南 读书笔记

    web性能权威指南 page 203 经典的性能优化最佳实践 无论什么网络,也不管所用网络协议是什么版本,所有应用都应该致力于消除或减 少不必要的网络延迟,将需要传输的数据压缩至最少.这两条标准是经典 ...

  7. Linux 文件搜索命令:find、which、whereis 和 locate

    Linux 提供了许多用于文件搜索的命令,这些命令都很强大,但是也有一些不同之处,这里分别介绍一下. 一.find 命令 find 是最常见和最强大的一个文件搜索命令.使用 find 命令可以在指定目 ...

  8. 图-最小生成树算法之Kruskal及其Java实现

    1.Kruskal算法 Kruskal算法基于贪心,因此它追求的是近似最优解,也就是说由Kruskal得出的生成树并不一定是最优解. Kruskal算法求最小生成树的关键在于,每次选取图中权值最小(及 ...

  9. 铁轨(rails, ACM/ICPC CERC 1997,Uva 514)

    铁轨(rails, ACM/ICPC CERC 1997,Uva 514) 题目描述 某城市有一个火车站,铁轨铺设如图所示.有n节车厢从A方向驶入车站,按进站顺序编号为1~n.你的任务是让它们按照某种 ...

  10. TensorFlow --- 01初识

    由于博客园对Markdown支持不够友好,阅读此文请前往云栖社区:TensorFlow --- 01初识