1.首先我们发现每个后缀开头一定是0,而且开头都是0..[若干个1]..0这种格式,按照字典序的排序方式那么如果两个0之间的1越少字典序就越小。例如aaaaab=>011110,aaab=>0110,那么我们设dis[i]就是第i位开始的往后延申有多少个是和开头字母相同的,如aaab=>dis[]={3,2,1,1};那么dis[i]越小对应数组的字典序一定越小1.首先我们发现每个后缀开头一定是0,而且开头都是0..[若干个1]..0这种格式,按照字典序的排序方式那么如果两个0之间的1越少字典序就越小。例如aaaaab=>011110,aaab=>0110,那么我们设dis[i]就是第i位开始的往后延申有多少个是和开头字母相同的,如aaab=>dis[]=\{3,2,1,1\};那么dis[i]越小对应数组的字典序一定越小1.首先我们发现每个后缀开头一定是0,而且开头都是0..[若干个1]..0这种格式,按照字典序的排序方式那么如果两个0之间的1越少字典序就越小。例如aaaaab=>011110,aaab=>0110,那么我们设dis[i]就是第i位开始的往后延申有多少个是和开头字母相同的,如aaab=>dis[]={3,2,1,1};那么dis[i]越小对应数组的字典序一定越小
2.还有一个明显的规律就是0的个数最多两个,因为出现了两个0说明ab和字母已经完全出现了,后面字母的B[]数组的值就不变了,那么我们可以对整个串求一遍B[]数组,在比较两个后缀的时候:我们先比较dis[i]和dis[j],如果dis[i]==dis[j]那么我们就比较后面的一截,根据字典序的定义比较第一个不相同的位置就可以了,那么我们就要求i+dis[i]和j+dis[j]后面的lcp,比较B[i+lcp+dis[i]]和B[j+lcp+dis[j]]就可以了2.还有一个明显的规律就是0的个数最多两个,因为出现了两个0说明ab和字母已经完全出现了,后面字母的B[]数组的值就不变了,那么我们可以对整个串求一遍B[]数组,在比较两个后缀的时候:我们先比较dis[i]和dis[j],如果dis[i]==dis[j]那么我们就比较后面的一截,根据字典序的定义比较第一个不相同的位置就可以了,那么我们就要求i+dis[i]和j+dis[j]后面的lcp,比较B[i+lcp+dis[i]]和B[j+lcp+dis[j]]就可以了2.还有一个明显的规律就是0的个数最多两个,因为出现了两个0说明ab和字母已经完全出现了,后面字母的B[]数组的值就不变了,那么我们可以对整个串求一遍B[]数组,在比较两个后缀的时候:我们先比较dis[i]和dis[j],如果dis[i]==dis[j]那么我们就比较后面的一截,根据字典序的定义比较第一个不相同的位置就可以了,那么我们就要求i+dis[i]和j+dis[j]后面的lcp,比较B[i+lcp+dis[i]]和B[j+lcp+dis[j]]就可以了
3.注意还有就是i+dis[i]会大于n,大于n相当于后面补0,在前面相同的情况下越短的字符串字典序越小3.注意还有就是i+dis[i]会大于n,大于n相当于后面补0,在前面相同的情况下越短的字符串字典序越小3.注意还有就是i+dis[i]会大于n,大于n相当于后面补0,在前面相同的情况下越短的字符串字典序越小


#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <limits.h>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define count Count
#define pb push_back
#define f first
#define s second
using namespace std;
const int N = 2e5+10, mod = 1e9 + 9;
const int maxn = 2e5 + 10;
const long double eps = 1e-5;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x)
{x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args)
{read(first);read(args...);
}char a[N];
int n;
int ord[N], pos[N], dis[N];struct SA {int sa[maxn], ra[maxn], height[maxn];int t1[maxn], t2[maxn], c[maxn];void build(int *str, int n, int m) {str[n] = 0;n++;int i, j, p, *x = t1, *y = t2;for (i = 0; i < m; i++) c[i] = 0;for (i = 0; i < n; i++) c[x[i] = str[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 (j = 1; j <= n; j <<= 1) {p = 0;for (i = n - j; i < n; i++) y[p++] = i;for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;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] + j] == y[sa[i] + j]) ? p - 1 : p++;if (p >= n) break;m = p;}n--;for (int i = 0; i <= n; i++) ra[sa[i]] = i;for (int i = 0, j = 0, k = 0; i <= n; i++) {if (k) k--;j = sa[ra[i] - 1];while (str[i + k] == str[j + k]) k++;height[ra[i]] = k;}st_init(height, n);}int lg[maxn], table[23][maxn];void st_init(int *arr, int n) {if (!lg[0]) {lg[0] = -1;for (int i = 1; i < maxn; i++)lg[i] = lg[i / 2] + 1;}for (int i = 1; i <= n; ++i)table[0][i] = arr[i];for (int i = 1; i <= lg[n]; ++i)for (int j = 1; j <= n; ++j)if (j + (1 << i) - 1 <= n)table[i][j] = min(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);}int lcp(int l, int r) {l = ra[l], r = ra[r];if (l > r) swap(l, r);++l;int t = lg[r - l + 1];return min(table[t][l], table[t][r - (1 << t) + 1]);}
} sa;bool cmp(int i, int j) {if (dis[i] != dis[j]) return dis[i] < dis[j];if (i + dis[i] > n) return true;if (j + dis[j] > n) return false;int lcp = sa.lcp(i + dis[i], j + dis[j]);return pos[i + lcp + dis[i]] < pos[j + lcp + dis[j]];
}int main()
{while(cin >> n >> a){int pa = -1, pb = -1;for(int i = 0; i < n; ++ i)if(a[i] == 'a'){if(pa == -1) pos[i] = 0;else pos[i] = i - pa + 1;pa = i;}else {if(pb == -1) pos[i] = 0;else pos[i] = i - pb + 1;pb = i;}pa = pb = -1;for(int i = n - 1; i >= 0; -- i)if(a[i] == 'a'){if(pb == -1) dis[i + 1] = n - i;else dis[i + 1] = pb - i;pa = i;}else {if(pa == -1) dis[i + 1] = n - i;else dis[i + 1] = pa - i;pb = i;}for(int i = 1; i <= n; ++ i) ord[i] = i;sa.build(pos,n,n+2);sort(ord+1,ord+1+n,cmp);for(int i = 1; i <= n; ++ i) printf("%d ",ord[i]);puts("");}return 0;
}

2020多校第1场A题【后缀数组+思维】相关推荐

  1. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  2. 2021牛客暑假多校第八场 K题—Yet Another Problem About Pi

    2021牛客暑假多校第八场 K题-Yet Another Problem About Pi 题意:告诉你一个单元格的长和宽,问你走Π(3.1415926-)的长度距离最多可以走几个单元格 思路:沿着单 ...

  3. 2020牛客多校第3场:[Points Construction Problem + 思维题+构造]

    题目链接 题目大意:就是给你n个边长为1的正方形,要求用这些正方形拼成周长为m的图形,并输出这些正方形的坐标,如果没有输出No 首先如果这些正方形都零散分布那么周长就是4∗n4*n4∗n,如果将这些正 ...

  4. 2020年牛客多校第五场C题-easy(纯组合计数不要生成函数的做法)

    文章目录 description solution code description 有TTT组测试数据 对于两个长度为KKK的数列{a}\{a\}{a}和{b}\{b\}{b},满足∑i=1Kai= ...

  5. 2020牛客暑期多校训练营(第九场)E题 Groundhog Chasing Death

    题意 计算 ∏ i = a b ∏ j = c d g c d ( x i , y j ) \prod_{i=a}^{b}\prod_{j=c}^{d}gcd(x^i,y^j) i=a∏b​j=c∏d ...

  6. HDU 2020 多校第七场 游记

    又是被 djq 带飞的一场 orz,终场 rk2,又是罚时被锤了 1001,1002 俩 hard 先略过,不会做 /ll 1003 这种数数神题被 djq 一眼秒了,我还能说什么-- 首先我们考虑合 ...

  7. 2018牛客暑期ACM多校训练营第二场 - A题

    A题是道水题--结果没注意到编译器不支持I64d卡了快俩小时-- 还要注意的是k=1时不是特例,因为这时候走跟跑还是不一样的-- A  run 输入描述: The first line of inpu ...

  8. 2022 年牛客多校第四场补题记录

    A Task Computing 题意:给定长度为 nnn 的序列 {(wi,pi)}\{(w_i,p_i)\}{(wi​,pi​)},从中选出 mmm 项并重新排列得到子序列 {a1,a2,⋯,am ...

  9. 2021杭电多校第八场补题

    比赛传送门:Contest Problem List (hdu.edu.cn) 1006)GCD Game 题目翻译:爱丽丝和鲍勃正在玩游戏. 他们轮流操作.有n个数字,a1,a2,...,an.每次 ...

最新文章

  1. Linux Centos 7 安装配置nginx
  2. 前端基础之JavaScript_1(二)
  3. 网联能否一统天下,取决于三个问题
  4. android edittext 手机号码,Android中EditText中的电话号码格式
  5. 中文件编码方式_一文解开java中字符串编码的小秘密
  6. [原创]WCF技术剖析之三:如何进行基于非HTTP的IIS服务寄宿
  7. ie6中 object doesn’t support this property or method
  8. Notepad ++添加到每一行
  9. LightOJ 1366 - Pair of Touching Circles (在矩形中只需要两个圆相外切,有多少种) 半径圆心均为整数)...
  10. java中有无穷大吗_Java语言中有无穷大
  11. 由《资深架构师带你玩转框架封装》课程——我的实践
  12. python查看函数帮助文档的方法
  13. 用C#打造quot;QQ对战平台挤房器quot;
  14. python 谷歌翻译_Python:谷歌翻译20次的程序如何实现?
  15. 小米浏览器导出html,小米浏览器离线视频如何导出 小米浏览器离线视频导出教程...
  16. matlab求一个矩阵的逆矩阵的命令,如何用MATLAB求逆矩阵
  17. sql 累计占比_sql 面试题(难题汇总)
  18. Hadoop大数据基础知识点总结--持续更新
  19. 中职计算机专业英语ppt,中职计算机英语教学方法论文
  20. vue导出excel加一个进度条_vue导出excel遇到的问题解决方法

热门文章

  1. ida 中segment中的extern是什么
  2. 王爽老师的汇编语言 实验8 jmp是如何实现跳转的
  3. EXE文件中的程序的加载过程 SA是什么呢?PSP是什么?
  4. 汇编语言 第3版 王爽 检测点习题部分—答案及详细解析 检测点3.2
  5. 复习计算机网络基础 day9--应用层
  6. Linux控制删除深度!除find ./ -maxdepth 1 -name *.c | xargs rm -rf
  7. 94. 二叉树的中序遍历(迭代)
  8. 混合云备份利用自定义Workflow保护MySQL的实践
  9. Acronis移动方案(四)
  10. sql server 怎么实现mysql中group_concat,列转行,列用分隔符拼接字符串