http://acm.hdu.edu.cn/showproblem.php?pid=5558

题意:

当前的位置是 i , 就找到 s1 = ( 以i为起点到 len 的连续串 ) , s2=( 在 [0,i)内选一个起点到 len 的连续串) , 要求s1==s2 ; 如果有输出( 最大的长度 , 在[0,i)内选取的起点 ) , 如果找不到就输出(-1 ,ASCLL(str[i]) )

分析:

利用SAM的联机特性 , 一边插入一边找答案 , 还要求最小的下标就多维护一个first_endpos

就是找到一个最大的某后缀 , 比如:从起始状态不断的用当前字符str[i] , 往后面转移 , 不断的p=trans[p][str[i]] , 就是说找到str[i]的最大后缀

#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i <= n; ++i)
const int maxn = 1e6+;
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
// __int128 read() { __int128 x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f;}
// void print(__int128 x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) print(x / 10); putchar(x % 10 + '0');} int len;
struct SAM{ int trans[maxn<<][], slink[maxn<<], maxlen[maxn<<];
// 用来求endpos
int endpos[maxn<<];
// 计算所有子串的和(0-9表示)
int last, now, root; inline void newnode (int v) {
maxlen[++now] = v;
mem(trans[now],);
} inline void extend(int c,int i) {
newnode(maxlen[last] + );
int p = last, np = now;
endpos[np]=i;
// 更新trans
while (p && !trans[p][c]) {
trans[p][c] = np;
p = slink[p];
}
if (!p) slink[np] = root;
else {
int q = trans[p][c];
if (maxlen[p] + != maxlen[q]) {
// 将q点拆出nq,使得maxlen[p] + 1 == maxlen[q]
newnode(maxlen[p] + );
int nq = now;
endpos[nq]=endpos[q];
memcpy(trans[nq], trans[q], sizeof(trans[q]));
slink[nq] = slink[q];
slink[q] = slink[np] = nq;
while (p && trans[p][c] == q) {
trans[p][c] = nq;
p = slink[p];
}
}else slink[np] = q;
}
last = np;
// 初始状态为可接受状态 } inline void init()
{
root = last = now = ;
slink[root]=;
mem(trans[root],);
//endpos[root]=0;
} }sam; int main()
{
//printf("%d ",maxn);
int t;scanf("%d",&t);
for(int w= ; w<=t ; w++){ string T;cin>>T;
sam.init();
len=T.size();printf("Case #%d:\n",w);
for(int i= ; i<len ; )
{
int p=sam.root , k=;
while(i < len && sam.trans[p][T[i]-'a'])
{
p=sam.trans[p][T[i]-'a'];
sam.extend(T[i]-'a',i);
k++ , i++;
}
//printf("%d\n",p);
if(k) printf("%d %d\n",k,sam.endpos[p]-k+);
else
{
sam.extend(T[i]-'a',i);
printf("-1 %d\n",(int)T[i]);
i++;
}
} }
//- sam.all();
}

HDU5558(后缀自动机~在本串中找前一最长子相同串)的更多相关文章

  1. java实现串中找数字

    串中找数字 以下的静态方法实现了:把串s中第一个出现的数字的值返回. 如果找不到数字,返回-1 例如: s = "abc24us43" 则返回2 s = "82445ad ...

  2. Leetcode30--->Substring with Concatenation of All Words(主串中找出连接给定所有单词的子串的位置)

    题目:给定一个字符串S(主串),一个字符串数组words,其中的字符串的长度相同.找到所有的子串位置,要求是words中字符串的一个连接: 举例: For example, given:s: &quo ...

  3. SPOJ 1811 Longest Common Substring (后缀自动机第一题,求两个串的最长公共子串)

    题目大意: 给出两个长度小于等于25W的字符串,求它们的最长公共子串. 题目链接:http://www.spoj.com/problems/LCS/ 算法讨论: 二分+哈希, 后缀数组, 后缀自动机. ...

  4. hdu 4763 Theme Section(next数组找串中三段相等)

    题意:在一个串中找 EAEBE 的形式的最长的E,其中E为一个字符串,也就是说找到前缀与后缀相同,并且串中还存在相同的一段,它们不能重复. 思路:利用next数组,next[len]代表的即是最大的相 ...

  5. KMP小扩展,找出子串在主串中出现的所有位置

    KMP算法能够高效地匹配字符串,找出子串(T串)在主串(S串)中出现的首个位置的原算法网上已经有很多优秀的博文进行详细讲解,这里就不多赘述. 这篇博文主要是对KMP原算法稍作改动,使其能够在主串中把所 ...

  6. 后缀自动机 && 题目

    因为明天要讲解后缀自动机了,所以只能抱抱佛脚,临时做做题目.其实很久以前看过,但是不太懂,看的是clj的原文,不太懂.现在只能临时看看是怎么弄的,应付下. ---------------------- ...

  7. D. Match & Catch 后缀自动机 || 广义后缀自动机

    http://codeforces.com/contest/427/problem/D 题目是找出两个串的最短公共子串,并且在两个串中出现的次数只能是1次. 正解好像是dp啥的,但是用sam可以方便很 ...

  8. 后缀自动机(SAM)奶妈式教程

    后缀自动机(SAM) 为了方便,我们做出如下约定: "后缀自动机" (Suffix Automaton) 在后文中简称为 SAM . 记 \(|S|\) 为字符串 \(S\) 的长 ...

  9. BZOJ 后缀自动机四·重复旋律7

    后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的 ...

随机推荐

  1. Luogu 4726 【模板】多项式指数函数

    补补补…… 这个题的解法让我认识到了泰勒展开的美妙之处. 泰勒展开 泰勒展开就是用一个多项式型的函数去逼近一个难以准确描述的函数. 有公式 $$f(x)\approx g(x) = g(x_0) + ...

  2. Linux网络配置之虚拟网卡的配置(Red Hat 6.5)

    怎么查看当前的网络状态,这里就不着重描述,用ifconfig命令就可以.我们直接进入主题. red hat系统中的网卡配置在这个目录中:/etc/sysconfig/network-scripts 1 ...

  3. charles4.2下载与破解方法以及配置https.RP

    Charles下载地址 地址:https://www.charlesproxy.com/latest-release/download.do 2. Charles破解 破解地址:https://www ...

  4. datatable:dt.page(dt.page()).draw(false)

    dt.page(dt.page()).draw(false);该方法可以直接返回到当前页,不用重新绘制table 描述 分页是DataTables的一个核心功能,并且该方法提供对表格显示页面的外部控制 ...

  5. 开发工具Visual Studio使用相关知识和经验的碎片化记录

    开发工具Visual Studio使用相关知识和经验的碎片化记录 1.Visual Studio提示"无法启动IIS Express Web服务器"的解决方法 有时,在使用Visu ...

  6. Perl 学习笔记-子程序

    1.定义子程序 使用sub关键字定义 ;   子程序名和标识符同要求, 但是有的特殊的可以用 &符号;  子程序是全局的, 不需要再使用前声明;  重名函数后者覆盖前者. sub roger{ ...

  7. java Random类和Math.Rondom

      Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取 ...

  8. C#中使用多线程访问Winform中控件的若干问题

    我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍. 首先来看传统方法: public partial  ...

  9. Activity Fragment转场动画

    Activity转场动画 先介绍个动画的好例子:https://github.com/lgvalle/Material-Animations Activity的转场动画是通过overridePendi ...

  10. java-设计模式汇总整理

    最近,对各种模式做了一个整理,便于后续自用. 1.工厂模式 总结:很好理解,一个接口,2个类实现这个接口,那么可以用“接口 变量=new 接口实现类”的方式调用不同的实现类,调用方式直接使用接口的方法 ...