题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5442

题目大意:给你一个长度为n的字符串,将它首尾相连成环。问你这个环上找一个长度为n的字典序最大的串(你可以沿顺时针或逆时针找),如果有多个这样的串,输出首字母标号最小的,如果还有多个,输出顺时针的

解:

1、最小表示法解(时间复杂度:O(n))

最小表示法~

2、后缀数组(时间复杂度:O(logn))

比赛的时候想到的方法,然而并没有写出来,不好写+高时间复杂度=不推荐

最小表示法:

 /*
* Problem:
* Author: SHJWUDP
* Created Time: 2015/9/16 星期三 16:18:36
* File Name: 1001.cpp
* State:
* Memo:
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm> using namespace std; struct KMP {
int n;
string T; //target string
vector<int> nt;
KMP(const char * _str) {
n=strlen(_str);
T.assign(_str, _str+n);
getFail();
}
void getFail() {
nt.resize(n+);
nt[]=-;
for(int i=, j=-; i<n; ) {
if(j==- || T[i]==T[j]) {
nt[++i]=++j;
} else j=nt[j];
}
}
int match(const char * P) {//pattern string
//在P中找T
int ret=-;
for(int i=, j=; P[i]; ) {
if(j==- || P[i]==T[j]) {
++i;
if(++j==n) {
if(P[i]) ret=i-n;
}
} else j=nt[j];
}
return ret;
}
}; int maximum_representation(const char * s) {
int i, j, k, len=strlen(s);
for(i=, j=, k=; i<len && j<len && k<len; ) {
int tmp=s[(i+k)%len]-s[(j+k)%len];
if(tmp==) ++k;
else {
if(tmp>) j+=k+;//改成小于号是最小表示法
else i+=k+;
if(i==j) ++j;
k=;
}
}
return min(i, j);
} int n;
int main() {
#ifndef ONLINE_JUDGE
freopen("in", "r", stdin);
//freopen("out", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
string str1;
cin>>str1;
int pos1=maximum_representation(str1.c_str());
string str2(str1.rbegin(), str1.rend());
int pos2=maximum_representation(str2.c_str());
str1+=str1;
str2+=str2;
KMP kmp(str2.substr(pos2, n).c_str());
pos2=kmp.match(str2.c_str());
auto cmp=[&]()->bool {
for(int i=; i<n; ++i) {
if(str1[pos1+i]!=str2[pos2+i])
return str1[pos1+i]>str2[pos2+i];
}
return pos1<=n-pos2-;
};
if(cmp()) {
printf("%d 0\n", pos1+);
} else {
printf("%d 1\n", n-pos2);
}
}
return ;
}

后缀数组:

 /*
* Problem:
* Author: SHJWUDP
* Created Time: 2015/9/14 星期一 16:06:34
* File Name: 1001.cpp
* State:
* Memo:
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm> using namespace std; struct SuffixArray {
static const int SIGMA_SIZE=;
int n;//串长+1
vector<int> str;//str中最后一个元素为0
vector<int> sa;//第i大后缀为str[sa[i]:]
vector<int> rank;//str坐标为i的后缀的字典序排名
vector<int> height;//sa[i-1]和sa[i]的最长公共前缀(LCP)
SuffixArray(const char * _str) {
n=strlen(_str)+;
str.resize(n);
for(int i=; i<n; ++i) str[i]=_str[i];
build_sa();
}
void build_sa(int m=SIGMA_SIZE) {
sa.assign(n, );
vector<int> x(n, ), y(n, ), c(m, );//c(字符计数)
//x[i]:str坐标为i的x值rank
//y[i]:y值第i大的str坐标
//*y数组中前k个为y段串不足k长度的串对应str坐标
for(int i=; i<n; ++i) ++c[x[i]=str[i]];
for(int i=; i<m; ++i) c[i]+=c[i-];
for(int i=n-; i>=; --i) sa[--c[x[i]]]=i;
for(int k=; k<=n; k<<=) {
int p=;
//直接利用sa数组排序第二关键字
for(int i=n-k; i<n; ++i) y[p++]=i;
for(int i=; i<n; ++i) if(sa[i]>=k) y[p++]=sa[i]-k;
//基数排序第一关键字
c.assign(m, );
for(int i=; i<n; ++i) ++c[x[y[i]]];
for(int i=; i<m; ++i) c[i]+=c[i-];
for(int i=n-; i>=; --i) sa[--c[x[y[i]]]]=y[i];
//根据sa和y数组计算新的x数组
swap(x, y);
p=; x[sa[]]=;
for(int i=; i<n; ++i) {
x[sa[i]]=y[sa[i-]]==y[sa[i]] && y[sa[i-]+k]==y[sa[i]+k]?p-:p++;
}
if(p >= n)break;
m = p;//下次基数排序的最大值
}
getHeight();
}
void getHeight() {
rank.resize(n);
height.resize(n);
for(int i=; i<n; ++i) rank[sa[i]]=i;
for(int i=, k=; i<n-; ++i) {
//h[i]=height[rank[i]]
if(k) --k; //h[i]>=h[i-1]-1
int j=sa[rank[i]-];
while(str[i+k]==str[j+k]) ++k;
height[rank[i]]=k;
}
}
}; int n;
bool cmp(string a, string b, int x, int y) {
for(int i=; i<n; ++i) {
if(a[x+i]!=b[y+i]) return a[x+i]>b[y+i];
}
return x<=n-y-;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in", "r", stdin);
//freopen("out", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
string str1;
cin>>str1;
string str2(str1.rbegin(), str1.rend());
str1+=str1;
str2+=str2;
SuffixArray sa1(str1.c_str());
int pos1;
for(int i=sa1.n-; i>=; --i) {
if(sa1.sa[i]<n) {
pos1=sa1.sa[i]; break;
}
}
SuffixArray sa2(str2.c_str());
int pos2=-, mi=n;
for(int i=sa2.n-; i>=; --i) {
if(pos2!=-) mi=min(mi, sa2.height[i+]);
if(mi<n) break;
if(sa2.sa[i]<n) pos2=sa2.sa[i];
}
if(cmp(str1, str2, pos1, pos2)) {
printf("%d 0\n", pos1+);
} else {
printf("%d 1\n", n-pos2);
}
}
return ;
}

hdu5442 Favorite Donut的更多相关文章

  1. hdu5442 Favorite Donut 后缀数组 长春网赛

    wa从一点到晚上11点没停过,也不知道为什么错,第二天换了个思路做,终于过了.这题还是有点问题的,数据有点水,我看到有人贴的代码baabbaab这组数据是4 0,明显错的,但是却可以过. 下面的是我第 ...

  2. 使用Donut Caching和Donut Hole Caching在ASP.NET MVC应用中缓存页面

    Donut Caching是缓存除了部分内容以外的整个页面的最好的方式,在它出现之前,我们使用"输出缓存"来缓存整个页面. 何时使用Donut Caching 假设你有一个应用程序 ...

  3. hdu 5442 Favorite Donut 后缀数组

    Favorite Donut Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid ...

  4. 使用 angular directive 和 json 数据 D3 随着标签 donut chart演示样本

    使用angular resource载入中priorityData.json中间json数据,结合D3绘制甜甜圈图.执行index.html其结果见于图.: priorityData.json中jso ...

  5. ASP.NET MVC 缓存扩展 - Donut Caching

    项目介绍 ASP.NET MVC Extensible Donut Caching brings donut caching to ASP.NET MVC 3 and later. The code ...

  6. HDU 5442——Favorite Donut——————【最大表示法+kmp | 后缀数组】

    Favorite Donut Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

  7. Hdu 5442 Favorite Donut (2015 ACM/ICPC Asia Regional Changchun Online 最大最小表示法 + KMP)

    题目链接: Hdu 5442 Favorite Donut 题目描述: 给出一个文本串,找出顺时针或者逆时针循环旋转后,字典序最大的那个字符串,字典序最大的字符串如果有多个,就输出下标最小的那个,如果 ...

  8. HDU 5442 Favorite Donut

    Favorite Donut Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

  9. Favorite Donut

    Favorite Donut Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

随机推荐

  1. MySql增删改查命令

    5.1 创建数据表 命令:create table <表名> ( <字段名1> <类型1> [,..<字段名n> <类型n>]); 例如,建 ...

  2. 剑指Offer:面试题29——数组中出现次数超过一半的数字(java实现)

    PS:在前几天的面试中,被问到了这个题.然而当时只能用最低效的方法来解. 问题描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2, ...

  3. Delete Exists

    Create PROCEDURE [dbo].[LVS_Update_WaferInfo] @LotId varchar(40), @xmlData xmlasBEGIN delete W from ...

  4. Android自学笔记:Git下载源代码

    Info:做J2ME几年了,现在基本没有公司用了,是时候向Android领域进军了. 自学中,难免会有疏漏,有问题请及时提出,共同学习共同进步. 2014-10-13:初版 2014-10-14:添加 ...

  5. Object-C 中各数据类型转换 NSData转NSString,Byte,UIImage

    1,NSData 与 NSString NSData --> NSString NSString *aString = [[NSString alloc] initWithData:adata ...

  6. 迁移学习( Transfer Learning )

    在传统的机器学习的框架下,学习的任务就是在给定充分训练数据的基础上来学习一个分类模型:然后利用这个学习到的模型来对测试文档进行分类与预测.然而,我们看到机器学习算法在当前的Web挖掘研究中存在着一个关 ...

  7. 2016-09-19: linux后台运行

    linux后台运行命令两种方式: 1. command & : 后台运行,你关掉终端会停止运行   2. nohup command & : 后台运行,你关掉终端也会继续运行 简介 L ...

  8. Spring Boot+Cloud RestTemplate 调用IP或域名

    在SpringBoot+Cloud的项目中,我们使用了自动配置的OAuth2RestTemplate,RestTemplate,但是在使用这些restTemplate的时候,url必须是服务的名称,如 ...

  9. 【JAVA】【Eclipse】出现This element neither has attached source nor attached Javadoc...的解决方法

    This element neither has attached source nor attached Javadoc and hence no Javadoc could be found Ec ...

  10. java静态和动态代理原理

    一.代理概念 为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类 ...