hdu 5442 Favorite Donut(后缀数组)
2015-09-16 10:44
211 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5442
题意:给定长度为n的字符串s(s是环),然后以某一点顺时针或者逆时针出发遍历字符串s将得到一个t,求一个字典序最大的字符串t的起始位置。字典序相同的选起始位置靠前的,位置相同的选顺时针的。
分析:将原来的字符串添加字符,使得前n个字符,每个字符与其后面的n-1个字符正是循环遍历的字符串。比如aabca--->aabcaaabc (顺时针) aabca---->acbaaacba (逆时针),然后对新构造出来的字符串求其后缀数组,那么可以得到字典序最大的两个字符串(两个方向),把字符串取出来,然后比较一下就行了。
ps:对于顺时针的字符串末尾要加一个表示负无穷的字符。这样保证后缀suffix(i)与suffix(j)的LCP等于其中一个后缀的时候,位置靠前的优先选择。
对于逆时针的字符串末尾要加一个表示正无穷的字符。这样保证后缀suffix(i)与suffix(j)的LCP等于其中一个后缀的时候,位置靠后的优先选择。这里的靠后是反转之后的字符串,再反过来就是靠前的了。
代码:
题意:给定长度为n的字符串s(s是环),然后以某一点顺时针或者逆时针出发遍历字符串s将得到一个t,求一个字典序最大的字符串t的起始位置。字典序相同的选起始位置靠前的,位置相同的选顺时针的。
分析:将原来的字符串添加字符,使得前n个字符,每个字符与其后面的n-1个字符正是循环遍历的字符串。比如aabca--->aabcaaabc (顺时针) aabca---->acbaaacba (逆时针),然后对新构造出来的字符串求其后缀数组,那么可以得到字典序最大的两个字符串(两个方向),把字符串取出来,然后比较一下就行了。
ps:对于顺时针的字符串末尾要加一个表示负无穷的字符。这样保证后缀suffix(i)与suffix(j)的LCP等于其中一个后缀的时候,位置靠前的优先选择。
对于逆时针的字符串末尾要加一个表示正无穷的字符。这样保证后缀suffix(i)与suffix(j)的LCP等于其中一个后缀的时候,位置靠后的优先选择。这里的靠后是反转之后的字符串,再反过来就是靠前的了。
代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <set> using namespace std; const int maxn = 1e5+6; char in[maxn],s[maxn]; int sa[maxn],t[maxn],t2[maxn],c[maxn],n; void build_sa(int n,int m) { int i,*x=t,*y=t2; for(i=0;i<m;i++) c[i]=0; for(i=0;i<n;i++) c[x[i]=s[i]]++; for(i=1;i<m;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1) { int p=0; for(i=n-k;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(i=0;i<m;i++) c[i]=0; for(i=0;i<n;i++) c[x[y[i]]]++; for(i=1;i<m;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n) break; m=p; } } void GetSuffix(char buf[],char str[],int p,int n) { for(int cnt=0,i=p;cnt<n;cnt++,i++) buf[cnt]=str[i]; buf ='\0'; } char ts[maxn],s1[maxn],s2[maxn]; int main() { int ncase,n,i,j,p1,p2,len1,len2; scanf("%d",&ncase); while(ncase--) { scanf("%d%s",&n,in); strcpy(ts,in); for(i=0;i<n-1;i++) ts[n+i]=ts[i]; ts[n+i]='\0'; len1=strlen(ts); strcpy(s,ts); build_sa(len1+1,255); for(i=len1;i>=0 && sa[i]>=n;i--);p1=sa[i]; GetSuffix(s1,ts,p1,n); strcpy(ts,in); reverse(ts,ts+n); for(i=0;i<n-1;i++) ts[n+i]=ts[i]; ts[n+i]='\0'; len2=strlen(ts); ts[len2]='z'+1; strcpy(s,ts); build_sa(len2+1,255); for(i=len2;i>=0 && sa[i]>=n;i--) ;p2=sa[i]; GetSuffix(s2,ts,p2,n); // printf("%s\n%s\n",s1,s2); p1=p1+1; p2=n-p2; int temp=strcmp(s1,s2); if(temp!=0) temp==1?printf("%d 0\n",p1):printf("%d 1\n",p2); else if(p1!=p2) p1<p2?printf("%d 0\n",p1):printf("%d 1\n",p2); else printf("%d 0\n",p1); } return 0; }
相关文章推荐
- 常量指针和指针常量
- spark调度系列------2. Spark Executor的创建和启动过程
- 不安装oracle客户端,用plsql连接oracle
- CodeForcesGym 100735H Words from cubes
- (大数据分析-3)HBASE Review
- 点滴感悟
- ios开发问题2—uitableviewController中如何改变tableview的位置
- 使用脚本便捷地在 Ubuntu 中安装最新 Linux 内核
- js 闭包概念
- cisco配置在线下载工具
- PHP Ajax 跨域问题最佳解决方案
- 君乐宝换奶粉方法
- android Service(一)
- 布局——线性布局、相对布局
- Android应用架构系列——ListView的模板化
- poj 3666
- html内嵌flex同时向flex页面传参实现pdf文档在线阅读
- iOS网络传输Delegate不被触发的本质原因
- 第三次作业
- 关于mock server