spoj 1812 lcsII (后缀自动机)
题意:求多个串的lcs,最多10个串,每个串最长10w
解题思路:后缀自动机。先建好第一个串的sam,然后后面的串拿上去跑(这个过程同前一题)。sam上,节点要记录两个信息,先说mi[p],其意思是p节点能匹配的所有串的最短的长度是多少,那我们如何更新这个mi呢?于是我们要记录另一个信息,mm[p]表示,跑当前串时,所跑到的节点能匹配的最大值,用这个最大值去更新mi。一个串跑完之后,要根据parent树,把mm往fa更新,然后用底下传上来的mm更新mi。怎么更新parent呢?很简单,我们知道,parent tree中父亲的代表串的长度必然比儿子短,所以我们只要根据代表串的长度排序,然后从后往前更新即可。
这题我有个小疑问,我们给mi赋初值时,用INF为何不可?而要用当前节点的val值呢?还望有知道的大神能不吝赐教啊。
- #include<stdio.h>
- #include<string.h>
- #include<algorithm>
- using namespace std ;
- const int maxn = 311111 ;
- int max ( int a , int b ) { return a > b ? a : b ; }
- int min ( int a , int b ) { return a < b ? a : b ; }
- int wv[maxn<<1] , ws[maxn<<1] ;
- int mm[maxn<<1] , mi[maxn<<1] ;
- struct sam {
- int fa[maxn<<1] , c[26][maxn<<1] , val[maxn<<1] , pos[maxn<<1] ;
- int tot , last ;
- inline int new_node ( int step ) {
- val[++tot] = step ;
- int i ;
- for ( i = 0 ; i < 26 ; i ++ ) c[i][tot] = 0 ;
- fa[tot] = 0 , mi[tot] = val[tot] ;
- return tot ;
- }
- void add ( int k ) {
- int p = last , i ;
- int np = new_node ( val[p] + 1 ) ;
- while ( p && !c[k][p] ) c[k][p] = np , p = fa[p] ;
- if ( !p ) fa[np] = 1 ;
- else {
- int q = c[k][p] ;
- if ( val[p] + 1 == val[q] ) fa[np] = q ;
- else {
- int nq = new_node ( val[p] + 1 ) ;
- for ( i = 0 ; i < 26 ; i ++ ) c[i][nq] = c[i][q] ;
- fa[nq] = fa[q] ;
- fa[q] = fa[np] = nq ;
- while ( p && c[k][p] == q ) c[k][p] = nq , p = fa[p] ;
- }
- }
- last = np ;
- }
- void build ( char *s ) {
- tot = 0 ;
- last = new_node ( 0 ) ;
- int len = strlen ( s ) , i ;
- for ( i = 0 ; i < len ; i ++ ) add ( s[i] - 'a' ) ;
- for ( i = 1 ; i <= tot ; i ++ ) wv[val[i]] ++ ;
- for ( i = 1 ; i <= tot ; i ++ ) wv[i] += wv[i-1] ;
- for ( i = 1 ; i <= tot ; i ++ ) ws[wv[val[i]]--] = i ;
- }
- void work ( char *s ) {
- int len = strlen ( s ) ;
- int p = 1 , i , temp = 0 ;
- for ( i = 0 ; i < len ; i ++ ) {
- int k = s[i] - 'a' ;
- if ( c[k][p] ) temp ++ , p = c[k][p] ;
- else {
- while ( p && !c[k][p] ) p = fa[p] ;
- if ( !p ) temp = 0 , p = 1 ;
- else temp = val[p] + 1 , p = c[k][p] ;
- }
- mm[p] = max ( mm[p] , temp ) ;
- }
- for ( i = tot ; i >= 1 ; i -- ) {
- p = ws[i] ;
- mi[p] = min ( mi[p] , mm[p] ) ;
- if ( fa[p] && mm[fa[p]] < mm[p] ) mm[fa[p]] = mm[p] ;
- mm[p] = 0 ;
- }
- }
- int solve () {
- int i , ans = 0 ;
- for ( i = 1 ; i <= tot ; i ++ )
- ans = max ( ans , mi[i]) ;
- return ans ;
- }
- } suf ;
- char s[maxn] ;
- int main () {
- // freopen ( "a.txt" , "r" , stdin ) ;
- scanf ( "%s" , s ) ;
- suf.build ( s ) ;
- int cnt = 0 ;
- while ( scanf ( "%s" , s ) != EOF ) {
- suf.work ( s ) ;
- // cnt ++ ;
- // if ( cnt == 2 ) break ;
- }
- printf ( "%d\n" , suf.solve () ) ;
- }
- /*
- skds
- fkds
- aajfaa
- */
spoj 1812 lcsII (后缀自动机)的更多相关文章
- SPOJ.1812.LCS2(后缀自动机)
题目链接 \(Description\) 求最多10个串的LCS(最长公共子序列). \(Solution\) 类比上题,对一个串建SAM,我们可以逐串地求出其在每个节点所能匹配的最大长度mx[i]. ...
- SPOJ 1812 LCS2 [后缀自动机 DP]
题意: 求多个串<=10的最长连续子串 一个串建SAM,然后其他串在上面走 每个状态记录所有串在这个状态的公共子串的最小值 一个串在上面走的时候记录与每个状态公共子串的最大值,注意出现次数向父亲 ...
- POJ.2774.Long Long Message/SPOJ.1811.LCS(后缀自动机)
题目链接 POJ2774 SPOJ1811 LCS - Longest Common Substring 确实比后缀数组快多了(废话→_→). \(Description\) 求两个字符串最长公共子串 ...
- SPOJ NSUBSTR Substrings 后缀自动机
人生第一道后缀自动机,总是值得纪念的嘛.. 后缀自动机学了很久很久,先是看CJL的论文,看懂了很多概念,关于right集,关于pre,关于自动机的术语,关于为什么它是线性的结点,线性的连边.许多铺垫的 ...
- 2018.12.15 spoj Substrings(后缀自动机)
传送门 后缀自动机基础题. 求长度为iii的子串出现次数的最大值. 对原串建出samsamsam,然后用sizsizsiz更新每个maxlenmaxlenmaxlen的答案. 然后由于后缀链接将其转化 ...
- SPOJ NSUBSTR Substrings ——后缀自动机
建后缀自动机 然后统计次数,只需要算出right集合的大小即可, 然后更新f[l[i]]和rit[i]取个max 然后根据rit集合短的一定包含长的的性质,从后往前更新一遍即可 #include &l ...
- Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)
Lexicographical Substrings Search \[ Time Limit: 149 ms \quad Memory Limit: 1572864 kB \] 题意 给出一个字符串 ...
- Substrings SPOJ - NSUBSTR (后缀自动机)
Substrings \[ Time Limit: 100ms\quad Memory Limit: 1572864 kB \] 题意 给出一个长度为 \(250000\) 的字符串,求出所有 \(x ...
- Longest Common Substring II SPOJ - LCS2 (后缀自动机)
Longest Common Substring II \[ Time Limit: 236ms\quad Memory Limit: 1572864 kB \] 题意 给出\(n\)个子串,要求这\ ...
随机推荐
- django开发简易博客(四)
上一节,我们讲述了怎么使用静态文件,并使用bootstrap对页面进行了美化,这一节我们将增强我们blog的功能,添加发表博客,删除博客的功能. 一.表单的使用 要实现添加blog的功能,就得使用表单 ...
- Android 开发笔记 “SharePreference 数据存取”
除了SQLite数据库外,SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息.其存储位置在/data ...
- Elasticsearch 1.4.X 的CORS设置
最近将Elasticsearch由1.2.2升级到1.4.4后,sense工具无法使用了,它发到Elasticsearch集群的请求没有任何的响应.阅读了Elasticsearch的文档才了解到,这是 ...
- 使用wget -i下载多个文件
使用wget -i下载多个文件 命令: wget -i filelist.txt 说明: 首先,保存一份下载链接文件 cat > filelist.txt url1 url2 url3 url4
- [LeetCode]题解(python):009-Palindrome Number
题目来源: https://leetcode.com/problems/palindrome-number/ 题意分析: 这题是要判断一个int是否一个回文数,要求不能申请额外的空间. 题目思路: 这 ...
- 转:STL使用入门( Using STL)
1 介绍 我最开始结束C++编程是从DOS下的Borland C++开始的.那时他们在最新版本3.1中就包含了一套模板库用来做collection.那真是个好东东.当我开始使用Visual C++ 2 ...
- perl 处理json 数组格式
[root@dr-mysql01 ~]# cat a1.pl use Encode; use JSON; use URI::Escape; use LWP::Simple; my $host = &q ...
- python异常处理URLError,HTTPError,Wrapping,
们在使用爬虫来抓取网页内容的时候,HTTP异常是必须要注意的一项,所以本文,我们来详细探寻一下HTTP异常处理的相关内容,通过一些具体的实例来分析一下,非常的简单,但是却很实用. 先来说一说HTT ...
- FMDB的基本应用
FMDB简介 iOS中原生的SQLite API在进行数据存储的时候,需要使用C语言中的函数,操作比较频繁.于是,就出现了一系列将AQLite API进行封装的库,例如FMDB.PlausibleDa ...
- Drainage Ditches(最大流)
Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 64044 Accepted: 2471 ...