codeforces128B——String
来源:互联网 发布:爱知中学高中部怎么样 编辑:程序博客网 时间:2024/06/10 15:47
1、题意:求一个字符串中所有子串按字典序从小到大排序后,第k小的子串是什么。
2、分析:这题好水这题思路简单,实现有一些细节。。
我们求出后缀数组,每一个后缀代表一些子串。要求第k小的,我们可以层层递进。先确定这个答案的第一个字符是什么,显然,最多才有26种字符,我们通过二分确定每一个字符对应的sa中的区间,然后判断第k小能否在这个区间里面。然后在确定第二个……
#include <map>#include <set>#include <cmath>#include <queue>#include <vector>#include <bitset>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define M 200010#define LL long long#define MOD 1000000007#define inf 2147483647#define llinf 4000000000000000000ll#define For(i, x, y) for(int i = (x); i < (y); i ++)#define rep(i, x, y) for(int i = (x); i <= (y); i ++)#define drep(i, x, y) for(int i = (x); i >= (y); i --)inline int read(){ char ch=getchar();int x=0,f=1; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}inline LL llread(){ char ch=getchar();LL x=0,f=1; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}char ch[M];int c[M], x[M], y[M], sa[M];inline void getsa(){ int n = strlen(ch), m = 200; ch[n ++] = '$'; For(i, 0, m) c[i] = 0; For(i, 0, n) c[x[i] = ch[i]] ++; For(i, 1, m) c[i] += c[i - 1]; drep(i, n - 1, 0) sa[-- c[x[i]]] = i; for(int k = 1; k <= n; k <<= 1){ int tot = 0; For(i, n - k, n) y[tot ++] = i; For(i, 0, n) if(sa[i] >= k) y[tot ++] = sa[i] - k; For(i, 0, m) c[i] = 0; For(i, 0, n) c[x[y[i]]] ++; For(i, 1, m) c[i] += c[i - 1]; drep(i, n - 1, 0) sa[-- c[x[y[i]]]] = y[i]; swap(x, y); tot = 1; x[sa[0]] = 0; For(i, 1, n){ x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? tot - 1 : tot ++); } if(tot >= n) break; m = tot; }// For(i, 1, n) cout << sa[i] << endl;} LL qsum[M];inline LL sum(int l, int r, int o){ return qsum[r] - qsum[l - 1] - 1ll * o * (r - l + 1);}int main(){ //freopen("0input.in", "r", stdin); scanf("%s", ch); int len = strlen(ch); getsa(); rep(i, 1, len) qsum[i] = qsum[i - 1] + len - sa[i]; int now_rank = read(), l = 1, r = len; if(now_rank > 1ll * len * (len + 1) >> 1ll) return puts("No such line."), 0; rep(i, 0, inf){ int left = l, right; //if(ch[sa[0] + i] == '$') left ++; rep(j, 'a', 'z'){ int ll = l, rr = r, ans = -1; while(ll <= rr){ int mid = (ll + rr) / 2; if(ch[sa[mid] + i] <= j) ll = (ans = mid) + 1; else rr = mid - 1; } if(ans == -1) continue; if(ch[sa[ans] + i] == 'z' + 1) left ++; if(ch[sa[ans] + i] != j) continue; right = ans; LL qt = sum(left, right, i); if(1 <= now_rank && now_rank <= right - left + 1){ return printf("%c", (char)(j)), 0; } if(1ll * now_rank <= qt){ printf("%c", (char)(j)); l = left, r = right; now_rank -= (r - l + 1); if(ch[sa[l] + i + 1] == '$') l ++; break; } //cout << qt << " " << now_rank << endl; now_rank -= qt; left = ans + 1; } } return 0;}
1 0
- codeforces128B——String
- C/C++——*string++、*++string、++*string的区别
- String——string-to-integer-atoi
- C#——String
- STL — — string
- STL —— string
- 实践——【String】
- Java——String
- Learning_log—string
- int —>string
- java—关于String
- 小瓜牛漫谈 — String
- String—常见功能
- String—Test
- LeetCode97—Interleaving String
- LeetCode344—Reverse String
- Javascript—String类型
- pyschools—Search String
- 欢迎使用CSDN-markdown编辑器
- Service学习之路(01)之Service简介及使用
- Service学习之路(02)之Service启动和停止Service
- 省市区县三级联动,用json文件本地加载
- 阿基米德螺旋线
- codeforces128B——String
- Service学习之路(03)之绑定本地Service并与之通信
- 维纳滤波
- Apache Curator入门实战
- 设计模式-行为设计模式:备忘录模式 Memento
- Android传输数据时加密详解
- spring基础概念1
- 系统性能监控利器-collectd详解
- 如何获取注册高德Key使用的SHA1值与包名?