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

相关文章

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Python Faker库基本用法详解

《PythonFaker库基本用法详解》Faker是一个非常强大的库,适用于生成各种类型的伪随机数据,可以帮助开发者在测试、数据生成、或其他需要随机数据的场景中提高效率,本文给大家介绍PythonF... 目录安装基本用法主要功能示例代码语言和地区生成多条假数据自定义字段小结Faker 是一个 python

Java Predicate接口定义详解

《JavaPredicate接口定义详解》Predicate是Java中的一个函数式接口,它代表一个判断逻辑,接收一个输入参数,返回一个布尔值,:本文主要介绍JavaPredicate接口的定义... 目录Java Predicate接口Java lamda表达式 Predicate<T>、BiFuncti

详解如何通过Python批量转换图片为PDF

《详解如何通过Python批量转换图片为PDF》:本文主要介绍如何基于Python+Tkinter开发的图片批量转PDF工具,可以支持批量添加图片,拖拽等操作,感兴趣的小伙伴可以参考一下... 目录1. 概述2. 功能亮点2.1 主要功能2.2 界面设计3. 使用指南3.1 运行环境3.2 使用步骤4. 核

一文详解JavaScript中的fetch方法

《一文详解JavaScript中的fetch方法》fetch函数是一个用于在JavaScript中执行HTTP请求的现代API,它提供了一种更简洁、更强大的方式来处理网络请求,:本文主要介绍Jav... 目录前言什么是 fetch 方法基本语法简单的 GET 请求示例代码解释发送 POST 请求示例代码解释

详解nginx 中location和 proxy_pass的匹配规则

《详解nginx中location和proxy_pass的匹配规则》location是Nginx中用来匹配客户端请求URI的指令,决定如何处理特定路径的请求,它定义了请求的路由规则,后续的配置(如... 目录location 的作用语法示例:location /www.chinasem.cntestproxy

CSS will-change 属性示例详解

《CSSwill-change属性示例详解》will-change是一个CSS属性,用于告诉浏览器某个元素在未来可能会发生哪些变化,本文给大家介绍CSSwill-change属性详解,感... will-change 是一个 css 属性,用于告诉浏览器某个元素在未来可能会发生哪些变化。这可以帮助浏览器优化

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

详解C++中类的大小决定因数

《详解C++中类的大小决定因数》类的大小受多个因素影响,主要包括成员变量、对齐方式、继承关系、虚函数表等,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 非静态数据成员示例:2. 数据对齐(Padding)示例:3. 虚函数(vtable 指针)示例:4. 继承普通继承虚继承5.

前端高级CSS用法示例详解

《前端高级CSS用法示例详解》在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交互和动态效果的关键技术之一,随着前端技术的不断发展,CSS的用法也日益丰富和高级,本文将深... 前端高级css用法在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交