SPOJ LCS 后缀自动机找最大公共子串
2024-10-21 03:16:45
这里用第一个字符串构建完成后缀自动机以后
不断用第二个字符串从左往右沿着后缀自动机往前走,如能找到,那么当前匹配配数加1
如果找不到,那么就不断沿着后缀树不断往前找到所能匹配到当前字符的最大长度,然后将cur节点转移到当前节点即可,再把答案加1
记住不断更新所能得到的最大值
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define M 26
#define N 600000
int cnt;
char s1[N] , s2[N]; struct SamNode{
SamNode *son[M] , *f;
int l;
}sam[N] , *root , *last; void init()
{
memset(sam , , sizeof(sam));
root = last = &sam[cnt=];
} void add(int x)
{
SamNode *p = &sam[++cnt] , *jp = last;
p->l = jp->l+;
last = p;
for(; jp&&!jp->son[x] ; jp=jp->f) jp->son[x] = p;
if(!jp) p->f = root;
else{
if(jp->l+ == jp->son[x]->l) p->f = jp->son[x];
else{
SamNode *r = &sam[++cnt] , *q = jp->son[x];
*r = *q;
r->l = jp->l+; q->f = p->f = r;
for(; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r;
}
}
} int solve(int len)
{
int ret = , maxn=;
SamNode *cur = root;
for(int i= ; i<len ; i++){
int x = s2[i]-'a';
if(cur->son[x]){
ret++;
cur = cur->son[x];
}
else{
while(cur && !cur->son[x]) cur = cur->f;
if(!cur) cur = root , ret=;
else{
ret = cur->l+;
cur = cur->son[x];
}
}
maxn = max(maxn , ret);
}
return maxn;
} int main()
{
// freopen("in.txt" , "r" , stdin);
// freopen("out.txt" , "w" , stdout);
scanf("%s%s" , s1 , s2);
init();
int len1 = strlen(s1) , len2 = strlen(s2);
for(int i= ; i<len1 ; i++) add(s1[i]-'a');
int ret = solve(len2);
printf("%d\n" , ret);
return ;
}
最新文章
- OpenStack中Keystone的基本概念理解
- sql server 写性能优化
- Cg关键字(keywords)
- volatile 用法
- FreeRTOS学习笔记——任务间使用队列同步数据
- Android SDK的下载和安装
- 浅谈c语言中的堆
- Oracle安装基本步骤
- 基于CDIF实现的——API在线自动化测试
- Javascript之pixi框架学习
- asp.net easyui 动态绑定下拉框
- JsonRequestBehavior不存在问题,JsonRequestBehavior属于哪个dll
- User-Agent 请求消息头
- 【OpenGL】搭建opgl环境
- MT【295】线段比的仿射变换
- 关于 DELPHI DATASNAP 的文章集
- mybatis generator生成文件大小写问题
- cdnbest设置301跳转
- JQuery实现1024小游戏
- MDX Cookbook 04 - 在集合中实现 NOT IN 逻辑 (Minus, Except, Filter 等符号和函数的使用)