【HDU5442】 Favorite Donut(后缀数组)
2015-09-15 14:06
309 查看
题意,给你一个长度为n的字符串,让你选择从某一个地方断开(可以正着取也可以反着取)。问你最大的字典序是从哪里断开。
首先先将原串复制一遍,然后用后缀数组求出字典序最大的位置,如果字典序相同则求出最靠前的位置。
然后再将该串翻转,得到反向取字典序最大的串,再直接比较就好了。
code:
首先先将原串复制一遍,然后用后缀数组求出字典序最大的位置,如果字典序相同则求出最靠前的位置。
然后再将该串翻转,得到反向取字典序最大的串,再直接比较就好了。
code:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 40005; char s ,ss ; int sa ,t ,t2 ; int Rank ,height ,c[300]; 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(int i = n - k ; i < n ; i ++) y[p ++] = i; for(int i = 0 ; i < n ; i ++) if(sa[i] >= k) y[p ++] = sa[i] - k; for(int i = 0 ; i < m ; i ++) c[i] = 0; for(int i = 0 ; i < n ; i ++) c[ x[i] ] ++; for(int i = 1 ; i < m ; i ++) c[i] += c[i - 1]; for(int i = n - 1 ; i >= 0 ; i --) sa[--c[x[y[i]]]] = y[i]; swap(x,y); p = 1;x[sa[0]] = 0; for(int 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 getheight(int n){ int i,j,k = 0; for(int i = 1 ; i <= n ; i ++) Rank[sa[i]] = i; for(int i = 0 ; i < n ; i ++){ if(k) k--; int j = sa[ Rank[i] - 1 ]; while(s[i + k] == s[j + k]) k ++; height[Rank[i]] = k; } } int n; void debug(){ for(int i = 0 ; i <= n ; i ++) printf("%d ",sa[i]); printf("\n"); for(int i = 0 ; i <= n ; i ++) printf("%d ",Rank[i]); printf("\n"); for(int i = 0 ; i <= n ; i ++) printf("%d ",height[i]); printf("\n"); } void cmp(int s1,int s2){ int flag = 0; for(int i = 0 ; i < n ; i ++){ if(ss[(s1 + i) % n] == ss[(s2 - i + n) % n]) continue; if(ss[(s1 + i) % n] > ss[(s2 - i + n) % n]) flag = 1; else flag = -1; if(flag != 0) break; } s1 ++,s2 ++; if(flag == 0){ if(s1 <= s2) printf("%d 0\n",s1); else printf("%d 1\n",s2); } else if(flag > 0) printf("%d 0\n",s1); else printf("%d 1\n",s2); } void solve(){ scanf("%d%s",&n,s); for(int i = 0 ; i < n ; i ++) ss[i] = s[n + i] = s[i]; s[n * 2] = 0; build_sa(n * 2 + 1,127); getheight(n * 2); int flag = 1,st1,st2; st1 = st2 = sa[0]; for(int i = 1 ; i <= n * 2 ; i ++){ if(height[i] < n) flag = 0; if(sa[i] >= n) continue; if(flag) st1 = min(st1,sa[i]); else{ flag = 1; st1 = sa[i]; } } for(int i = 0 ; i < n ; i ++) swap(s[2 * n - 1 - i],s[i]); s[n * 2] = 0; build_sa(n * 2 + 1,127); getheight(n * 2); flag = 1; for(int i = 1 ; i <= n * 2 ; i ++){ if(height[i] < n) flag = 0; if(sa[i] >= n) continue; if(flag) st2 = min(st2,n - 1 - sa[i]); else{ flag = 1; st2 = n - 1 - sa[i]; } } cmp(st1,st2); } int main(){ int _; scanf("%d",&_); while(_--) solve(); return 0; }
相关文章推荐
- apache 的常用:1反射赋值方法 2数组追加字符、填充fill、集合转化为数组
- Linux鸟哥私房菜学习笔记--第九章
- Linux 下安装ffmpeg(xlib264 yams)
- Qt 学习之路:线程和 QObject
- LeetCode_best-time-to-buy-and-sell-stock-ii
- 常用存储过程
- 可做弊的年会抽奖程序
- LSTM实现详解
- 通过读取excel数据和mysql数据库数据做对比(一)-win环境准备
- 浅谈单片机应用程序架构
- myeclipse中SVN插件安装方法
- Hibernate 入门教程(纯Eclipse版)
- Struts 2 Hello World Example
- jQuery动态创建html元素的常用方法汇总
- 使用环信给App推送Push消息
- 常用的js工具库
- 《黑马程序员》 初识黑马
- MonkenRunner之HierarchyViewer API教程
- dataWithContentsOfURL报错问题
- mysql常用函数