题目链接: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. 解决VML遭遇IE8和XHTML DOCTYPE时不能运行的问题(转)

    原文网址:http://blog.csdn.net/cuixiping/article/details/4227283  以下代码在IE运行正常 <!DOCTYPE HTML PUBLIC &q ...

  2. samba服务器搭建小记

    经常要在局域网的linux和windows主机之间共享文件,我遇到了当年samba作者同样的问题,既然人家已经写好了这个软件那就直接拿来用吧. 首先,在linux主机上执行 sudo apt-get ...

  3. 预装WIN8系统的电脑安装WIN7的方法

    前些天,给一位客户的本本安装WIN7,因为原来预装了WIN8,结果按常规方法安装一直没有成功,不管是光盘还U盘.所以心里一直有个疑问,所以留意查阅了有关资料和相关的文章,终于明白了问题所在,现在在这里 ...

  4. OpenCV2.3.1在Win7+VS2010下的配置过程(转)

    转自:http://blog.csdn.net/mygis2005/article/details/10472717 这篇博客很好的解决了我遇到的问题,所以转到自己的博客里,方便以后进行查阅. 1.  ...

  5. 【练习】数据移动---导入(IMPDP)

    1.导入表并验证: :: SYS@ORA11GR2>grant connect,resource to jj identified by jj; Grant succeeded. :: SYS@ ...

  6. JAVA 多线程和并发学习笔记(三)

    Java并发编程中使用Executors类创建和管理线程的用法 1.类 Executors Executors类可以看做一个“工具类”.援引JDK1.6 API中的介绍: 此包中所定义的 Execut ...

  7. Mysql 数据库创建基本步骤

    1.创建数据库 create database school; 2.使用数据库 Use school; 3.创建用户 create user jame@localhost identified by ...

  8. python的optparse模块使用

    name or flags:就是参数的名称或标志 -f --file,-q --quit 等,其中-f表示option的缩写,--file表示option的全称 nargs:命令行参数的个数,一般使用 ...

  9. hibernate的环境配置

    1,首先把跟Hibernate相关的jar包导入到lib目录下: 2,写Javabean类 package chen.can.Dao; public class TRegister implement ...

  10. Li-Fi,LED光无线局域网

    无需WiFi信号,点一盏LED灯就能上网.昨天,复旦大学计算机科学技术学院传出好消 息,一种利用屋内可见光传输网络信号的国际前沿通讯技术在实验室成功实现.研究人员将网络信号接入一盏1W的LED灯珠,灯 ...