[BZOJ2946][Poi2000]公共串解题报告|后缀自动机
鉴于SAM要简洁一些...于是又写了一遍这题...
不过很好呢又学到了一些新的东西...
这里是用SA做这道题的方法
首先还是和两个字符串的一样,为第一个字符串建SAM
然后每一个字符串再在这个SAM上跑匹配
然而我们最后要的答案是什么呢?
是某个在所有字符串中匹配长度最小值最大的状态子串
然后对于每一个字符串
我们可以记录它在每一个状态子串上的最大匹配长度
最后需要一个非常关键的转移
就是用当前节点的值更新fail指针指向的节点
比如这种情况
如果一次匹配到左边的三个节点,一次匹配到右边的两个节点(两次匹配在不同的字符串中)
那么显然,这两个字符串的公共子串长度为2是存在的
但是由于我们没有转移过,fail指针指向的点没有储存前面的信息就会出错
然后至于转移的顺序,我们可以按照深度顺序
这个可以用桶排实现
program bzoj2946;
const maxn = ;
var n,i,j,now,maxl,root,c,tot,cnt,t:longint;
s:array[..]of ansistring;
mx,fail,q,b,ans,tem:array[-..maxn]of longint;
a:array[-..maxn,-..]of longint; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end; function insert(p,c:longint):longint;
var np,q,nq:longint;
begin
inc(cnt);np:=cnt;mx[np]:=mx[p]+;
while (p<>)and(a[p,c]=) do
begin
a[p,c]:=np;p:=fail[p];
end;
if p= then fail[np]:=root else
begin
q:=a[p,c];
if mx[q]=mx[p]+ then fail[np]:=q else
begin
inc(cnt);nq:=cnt;mx[nq]:=mx[p]+;
a[nq]:=a[q];
fail[nq]:=fail[q];
fail[np]:=nq;fail[q]:=nq;
while a[p,c]=q do
begin
a[p,c]:=nq;p:=fail[p];
end;
end;
end;
exit(np);
end; begin
readln(n);
for i:= to n do readln(s[i]);
cnt:=;root:=;t:=root;
for i:= to length(s[]) do t:=insert(t,ord(s[,i])-);
for i:= to cnt do ans[i]:=mx[i];
fillchar(b,sizeof(b),);
for i:= to cnt do inc(b[mx[i]]);
for i:= to cnt do inc(b[i],b[i-]);
for i:= to cnt do ans[i]:=mx[i];
for i:=cnt downto do
begin
dec(b[mx[i]]);
q[b[mx[i]]]:=i;
end;
for i:= to n do
begin
now:=root;maxl:=;
fillchar(tem,sizeof(tem),);
for j:= to length(s[i]) do
begin
c:=ord(s[i][j])-;
if a[now,c]<> then begin now:=a[now,c];inc(maxl);end else
begin
while (now<>)and(a[now,c]=) do now:=fail[now];
if now= then begin now:=root;maxl:=;end else begin maxl:=mx[now]+;now:=a[now,c];end;
end;
tem[now]:=max(tem[now],maxl);
end;
for j:=cnt downto do tem[fail[q[j]]]:=max(tem[fail[q[j]]],tem[q[j]]);
for j:= to cnt do ans[j]:=min(ans[j],tem[j]);
end;
tot:=;
for i:= to cnt do if ans[i]>tot then tot:=ans[i];
writeln(tot);
end.
比较了一下..代码减少了三分之一,空间缩小了十分之九...最主要写起来简单多了
SAM大法好
05/.May
[BZOJ2946][Poi2000]公共串解题报告|后缀自动机的更多相关文章
- [BZOJ2946] [Poi2000]公共串解题报告|后缀数组
给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 单词个数<=5,每个单词长度<=2000 尽管最近在学的是SAM...但是看到这个题还是忍不住想写SA... (其实是不 ...
- [codevs3160]最长公共子串解题报告|后缀自动机
给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 样例就觉得不能更眼熟啊...好像之前用后缀数组做过一次 然后发现后缀自动机真的好好写啊...(当然当时学后缀数组的时候也这么认为... 这 ...
- BZOJ2946 Poi2000 公共串 【后缀自动机】
Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单词 l 计算最长公共子串的长度 l 输出结果 Input 文件的第一行是整数 n,1<=n& ...
- [bzoj2946][Poi2000]公共串_后缀数组_二分
公共串 bzoj-2946 Poi-2000 题目大意:给定$n$个字符串,求他们的最长公共子串. 注释:$1\le n\le 5$,$1\le minlen<maxlen\le 2000$. ...
- SPOJ1812: LCS2 - Longest Common Substring II & BZOJ2946: [Poi2000]公共串
[传送门:SPOJ1811&BZOJ2946] 简要题意: 给出若干个字符串,求出这些字符串的最长公共子串 题解: 后缀自动机 这两道题的区别只是在于一道给出了字符串个数,一个没给,不过也差不 ...
- BZOJ2946 [Poi2000]公共串(后缀自动机)
Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单词 l 计算最长公共子串的长度 l 输 ...
- bzoj2946 [Poi2000]公共串(SA,SAM)
[题意] 多串求LCS. [思路] 主要是想找一下SAM的优越感 :) velui good 后缀数组划分height需要注意不少细节 <_<,然后不停debug [代码] ...
- 【二分答案】【分块答案】【字符串哈希】【set】bzoj2946 [Poi2000]公共串
我们二分/分块枚举答案x,暴力把除了最短的字符串以外的其他字符串的x长度子串哈希搞出来,分别扔到set里. 然后暴力枚举最短的字符串的x长度字串,查看是否在全部的set里出现过. #include&l ...
- bzoj2946: [Poi2000]公共串
SAM处女题qwq #include <iostream> #include <cstdio> #include <cstring> #include <cm ...
随机推荐
- java连接数据库的两种方法总结
方法一:使用jdbc-odbc桥连接sql server,作为中间媒介连接数据库 1.配置数据源:打开控制面版->管理工具->数据源(ODBC)->选用户DSN,按下添加按钮-> ...
- iOS音频播放概述
在iOS系统中apple对音频播放需要的操作进行了封装并提供了不同层次的接口 下面对其中的中高层接口进行功能说明: Audio File Services:读写音频数据,可以完成播放流程中的第2步: ...
- redis切换数据库的方法【jedis】
package com.test; import redis.clients.jedis.Jedis; public class readredis { public static void main ...
- AjaxPro怎么用
AjaxPro是首家支持以各种方式通过javascript访问服务端.net的免费库,类似于SAJAX.它能把Javascript请求发送到.NET方法,服务端传回给Javascript,甚至包括串行 ...
- 【转】how can i build fast
http://blog.csdn.net/pcliuguangtao/article/details/5830860
- java基础简介
一.软件开发 软件:是由数据和指令组成的(例:计算器) 如何实现软件开发呢? 就是使用开发工具和计算机语言做出东西来 二.常用dos命令 d: 回车 盘符切换 dir(directory):列出 ...
- fzu1686-神龙的难题
给出一个n\times m的01矩阵,以及\(h,w\),表示一次可以把矩阵的一个\(h\times w\)的小矩阵变为全0,问至少要多少次可以把整个矩阵变为全0.\(n,m\le 15\). 分析 ...
- BZOJ 1296 粉刷匠(分组背包套DP)
刚开始往网络流的方向想.建不出图... 因为每次只能对一行进行染色.每一行都是独立的. 对于每一行,因为格子只能染一次,所以可以发现这是一个多阶段决策问题,这个决策就是当前格子染0还是染1. 令dp[ ...
- (转)python 搭建libsvm方法。python版本和libsvm版本匹配很重要!
<集体智慧编程>关于婚介数据集的SVM分类 转自:http://muilpin.blog.163.com/blog/static/165382936201131875249123/ 作 ...
- [LOJ2540] [PKUWC2018] 随机算法
题目链接 LOJ:https://loj.ac/problem/2540 Solution 写的时候脑子不太清醒码了好长然后时间\(LOJ\)垫底... 反正随便状压\(dp\)一下就好了,设\(f[ ...