poj 3581 后缀数组 详解

2024-05-28 05:08
文章标签 数组 详解 后缀 poj 3581

本文主要是介绍poj 3581 后缀数组 详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这个题折腾了快一个月,终于今晚又奋战了4个小时,AC掉了

题目:http://poj.org/problem?id=3581

首先看我写这个后缀数组教程,其实还不错http://blog.csdn.net/u011026968/article/details/20851295

关于第一个位置,反向读入,然后求后缀数组,找最小位置就好

第二个位置比较麻烦,参考这个博客的例子:http://bbezxcy.iteye.com/blog/1420546

大致思路:

    由于需要翻转,所以在输入时就按照反序输入。比如样例输入是5     10 1 2 3 4。我们从后向前读入就变为5     4 3 2 1 10。对这列数求出后缀数组。在大于2的后最中找到最小的后缀并输出。对于剩下的前缀s,我们把s串接到自己后面,也就是ss。再对这个串求出后缀数组,然后再把s中最小的前缀输出。最后把剩下的串输出。

 

对于第二步为什么要复制剩余串接在后面,用下面案例说明

6

10 1 2 2 3 4

 

第一步翻转后得到

4 3 2 2 1 10

 

求出后缀数组后得到最小的后缀便是:1 10,将其输出

剩下来的串是 4 3 2 2.

 

我们如果直接从剩余串中找到最小后缀的话会产生以下结果。

最小后缀是 2,输出。

输出剩余串 4 3 2。

最后得到1 10 2 4 3 2  很明显是wrong的

 

 

我们把剩余的串复制到剩余串的后面。

对 4 3 2 2 4 3 2 2求出后缀数组。

得到前四个字符的最小的后缀是 2 2,输出。

输出剩余串 4 3.

得到1 10 2 2 4 3 

 

这里解释了为啥不能直接对剩下的串求后缀数组

我个人除了很多问题,,,,我再想想做个总结,随后附上


/*******************************************************/
//POJ 3581 后缀数组   by Pilgrim
//注意:1、此代码中k是全局变量 别乱用
//     2、algorithm
//     3、注意此题的字典序的定义,跟往常不一样的
//     4、因为有负数所以最小的应该是int的下限而不是0
/******************************************************/#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <vector>#define MAXN 300005*2
#define INF -200000000
//0x80000000using namespace std;int n,k,pp,mm;
int num[MAXN],rr[MAXN];
int Rank[MAXN],tmp[MAXN],sa[MAXN];bool cmpSa(int i, int j)
{if(Rank[i]!=Rank[j]){return Rank[i]<Rank[j];}else{int ik = i+k<=n?Rank[i+k]:-INF-1;int jk = j+k<=n?Rank[j+k]:-INF-1;return ik<jk;}
}bool cmpSa2(int i, int j)
{if(Rank[i]!=Rank[j]){return Rank[i]<Rank[j];}else{int ik = i+k<=pp?Rank[i+k]:-INF-1;int jk = j+k<=pp?Rank[j+k]:-INF-1;return ik<jk;}
}bool cmpSS(int i,int j)
{return rr[i]<rr[j];
}void con_sa(int s,int e)
{int i,j;//sort(tmp+s,tmp+e+1,cmpSS);for(i=s;i<=e;i++)Rank[i]=rr[i];Rank[e]=INF;//printf("%d tmp=%d rank=%d\n",i,tmp[i],Rank[tmp[i]]);/*此时的rank已经能表示相对大小*/for(k=1;k<=e;k*=2){if(mm){pp=e;sort(sa+s,sa+e+1,cmpSa2);}else{sort(sa+s,sa+e+1,cmpSa);}tmp[sa[s]]=s;for(i=s+1;i<=e;i++){tmp[sa[i]]=tmp[sa[i-1]]+(cmpSa(sa[i-1],sa[i])?1:0);}for(i=s;i<=e;i++)Rank[i]=tmp[i];}
}void show(int p1,int p2)
{for(int i=p1;i<n;i++)printf("%d\n",num[i]);for(int i=p2;i<p1;i++)printf("%d\n",num[i]);for(int i=0;i<p2;i++)printf("%d\n",num[i]);
}void Init()
{memset(tmp,0,sizeof(tmp));memset(Rank,0,sizeof(Rank));memset(sa,0,sizeof(sa));for(int i=0;i<n;i++){scanf("%d",&num[i]);rr[n-i-1] = num[i];/*rr是整个反转后的串,*/sa[i]=i;}sa[n]=n;for(int i=0;i<=n;i++){num[i]=rr[i];tmp[i]=i;}
}void Init2(int e)
{memset(tmp,0,sizeof(tmp));memset(Rank,0,sizeof(Rank));memset(sa,0,sizeof(sa));for(int i=0;i<e;i++){rr[i+e] = rr[i];}for(int i=e*2;i<=2*n;i++)rr[i]=INF;for(int i=0; i<=e*2; i++){sa[i]=tmp[i]=i;tmp[i]=i;}
}int main()
{//freopen("poj 3581.txt","r",stdin);int p1,p2;scanf("%d",&n);mm=0;Init();con_sa(0,n);for(int i=0;i<=n;i++){p1=sa[i];if(p1>=2 && p1<n)break;}mm=1;Init2(p1);con_sa(0,p1*2);for(int i=0; i<=p1*2;i++){p2=sa[i];if(p2>=1 && p2<p1)break;}show(p1,p2);return 0;
}



这篇关于poj 3581 后缀数组 详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1009618

相关文章

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

SQL Server 中的 WITH (NOLOCK) 示例详解

《SQLServer中的WITH(NOLOCK)示例详解》SQLServer中的WITH(NOLOCK)是一种表提示,等同于READUNCOMMITTED隔离级别,允许查询在不获取共享锁的情... 目录SQL Server 中的 WITH (NOLOCK) 详解一、WITH (NOLOCK) 的本质二、工作

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

Spring AI使用tool Calling和MCP的示例详解

《SpringAI使用toolCalling和MCP的示例详解》SpringAI1.0.0.M6引入ToolCalling与MCP协议,提升AI与工具交互的扩展性与标准化,支持信息检索、行动执行等... 目录深入探索 Spring AI聊天接口示例Function CallingMCPSTDIOSSE结束语