【spoj2774】最长公共子串
题目描述:
给你两个字符串,求它们最长公共子串的长度,如果不存在公共子串则输出0。
样例输入:
yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother
样例输出:
27
题解:
SAM果题。
代码+SAM理解记录附下:
//
// Title : SAMachine
// Date : 10.03.2016
// Test : CODEVS-3160
// Complexity : O(n)
//
/*
对于子串匹配/处理等问题——
解决办法:后缀自动机
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> #ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif #ifdef CT
#define debug(...) printf(__VA_ARGS__)
#else
#define debug(...)
#endif #define R register
#define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
#define gmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define gmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1<<15],*S=B,*T=B;
inline int FastIn()
{
R char ch;R int cnt=0;R bool minus=0;
while (ch=getc(),(ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ?minus=1:cnt=ch-'0';
while (ch=getc(),ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus?-cnt:cnt;
}
#define maxn 250010
char str[maxn] ;
int ans ;
struct SAM
{
int p , np , q , nq;
int cnt , last;
int a[maxn][26] , l[maxn] , fa[maxn];
SAM()
{
last=++cnt;
}
void extend(R int c)
{
p = last ; // p表示添加前的最后一个状态
np = last = ++cnt; // np表示当前的状态
l[np] = l[p] + 1; // 当前的长度为上一个状态的长度+1
for (; !a[p][c] && p ; ) a[p][c] = np , p = fa[p] ; // 如果p的fail指针的trie边没有被占用,那么就将其trie边连到np上
if (!p) fa[np] = 1 ; // 如果当前这单个字符没有出现过,那么就把当前状态的fail指针设为1(init,初始状态)
else // 如果p的fail指针被占用了,那么就————
{
q = a[p][c]; // q表示被占用掉的那个状态
if (l[p] + 1 == l[q] ) fa[np] = q; // 如果这个状态刚好是当前状态的上一个字符的状态,那么就意味着出现了两个相同的字符,此时就直接将fail指针建到q上
else // 否则就
{
nq = ++cnt ; // 新建一个节点
l[nq] = l[p] + 1 ; // 新建的这个节点将会的长度等于当前状态的长度
memcpy (a[nq] , a[q] , sizeof (a[q]) ); // 将当前占用掉的那个状态的trie边连到新的节点上
fa[nq] = fa[q] ; // 新建节点的fail指针指向上一个状态
fa[np] = fa[q] = nq ; // 当前的节点和被占用的节点的fail指针指向新的节点
while (a[p][c] == q) a[p][c] = nq , p = fa[p] ; // 把所有trie边指向q的点的trie边连向nq
}
}
}
void build()
{
scanf( "%s\n" , str );
for (R int i = 0 ; str[i] ; i++ ) extend ( str[i] - 'a' ) ;
}
void solve()
{
scanf( "%s\n" , str );
R int tmp = 0;
for (R int i = 0 ; str[i] ; i++ )
{
R int c = str[i] - 'a';
if ( a[p][c] ) p = a[p][c] , tmp ++ ;
else
{
for ( ; p && !a[p][c] ; ) p = fa[p] ;
if (!p) p = 1 ,tmp = 0;
else tmp = l[p] + 1 , p = a[p][c];
}
cmax( ans , tmp );
}
printf("%d\n",ans );
}
}sam;
int main()
{
sam.build();
sam.solve();
return 0;
}
【spoj2774】最长公共子串的更多相关文章
- [Data Structure] LCSs——最长公共子序列和最长公共子串
1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...
- HDU 1503 带回朔路径的最长公共子串
http://acm.hdu.edu.cn/showproblem.php?pid=1503 这道题又WA了好几次 在裸最长公共子串基础上加了回溯功能,就是给三种状态各做一个 不同的标记.dp[n][ ...
- 最长公共子序列PK最长公共子串
1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. (1)递归方法求最长公共子序列的长度 1) ...
- 动态规划(一)——最长公共子序列和最长公共子串
注: 最长公共子序列采用动态规划解决,由于子问题重叠,故采用数组缓存结果,保存最佳取值方向.输出结果时,则自顶向下建立二叉树,自底向上输出,则这过程中没有分叉路,结果唯一. 最长公共子串采用参考串方式 ...
- 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774
Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在 ...
- 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message
Language: Default Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 21 ...
- 最长公共子串 NYOJ 36
http://acm.nyist.net/JudgeOnline/problem.php?pid=36 最长公共子序列 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 ...
- POJ 2217 (后缀数组+最长公共子串)
题目链接: http://poj.org/problem?id=2217 题目大意: 求两个串的最长公共子串,注意子串是连续的,而子序列可以不连续. 解题思路: 后缀数组解法是这类问题的模板解法. 对 ...
- poj1159 dp最长公共子串
//Accepted 204 KB 891 ms //dp最长公共子串 //dp[i][j]=max(dp[i-1][j],dp[i][j-1]) //dp[i][j]=max(dp[i][j],dp ...
随机推荐
- sql回显注入-笔记
拼接sql命令查询数据 注释 常用于sql注入 # 井号 单行注释 注意:URL编码 %23 -- 两个减号加空格 单行注释 /* ...
- shell脚本一键部署nginx
一键部署nginx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ...
- 引入父目录模块 import
a : a1.py a2.py b : b1.py 其中 a, b 同目录,现在想在b1中引用a1里面内容 在b1中需要进行进行如下操作 x = path.join('..') sys.path.ap ...
- mongodb增删改查常用命令总结
前言 去年我还折腾过mongodb,后来用不到也就没碰了,这就导致了我忘的一干二净,不得不感叹,编程这东西只要不用,就会忘没了.现在我想重拾mongodb,来总结一下常用命令,主要就是增删改查. 另外 ...
- 洛谷 P5150 生日礼物 题解
题面 因为 n=lcm(a,b)n = lcm(a, b)n=lcm(a,b) ,可以得出: a 和 b 的质因数都是 n 的质因数 对于 n 的每个质因数 x ,在 n 中的次数为 y ,那么 ...
- python-day15(正式学习)
目录 递归 函数自我嵌套 调用 直接调用 间接调用 为什么要用递归呢 如何使用递归 内置函数 掌握 了解 面向对象方法 面向过程编程 注册 分层实现功能 递归 递归的本质就是函数调用自身,当然也会有一 ...
- sql server 函数详解(2)数学函数
绝对值函数ABS(x)和返回圆周率的函数PI() 平方根函数SQRT(x) 获取随机函数的函数RAND()和RAND(x) 四舍五入函数ROUND(x,y) 符号函数SIGN(x) 获取整数的函数CE ...
- 解决jenkins的Console Output中文乱码
1.本地机器设置环境变量(设置后需要注销计算机才能生效) key: JAVA_TOOL_OPTIONS value:-Dfile.encoding=UTF- 2. 通过Jenkins全局设置的方式 ...
- vue单页应用中根据不同城市不同业务添加百度统计代码
问题描述: 我们知道一般的百度统计代码是添加在html的head里的:但是,因为目前项目是用vue开发的单页应用,所以在路由跳转之间不会刷新页面, 统计代码如果放在项目里的index.heml的hea ...
- 神奇的AI:将静态图片转为3D动图
近日我们从外媒获得消息,位于莫斯科的三星AI中心和Skolkovo科学技术研究所的研究人员发表了一篇新论文,详细介绍了从单个静止人像照片生成3D动画人像的创建.与此前能够生成照片般逼真肖像的人工智能A ...