比赛题目训练系列15 (2020牛客暑期多校训练营(第一场))

比赛题目训练系列15 (2020牛客暑期多校训练营(第一场))

训练网址

B-Suffix Array

  • 定义一个B函数,计算一个字符串所有后缀的B函数,然后对这些后缀所得的 B B B 函数的值进行字典序排序。输出排名为 1 ~ N 的后缀首字母对应原字符串的下标。
  • 题解给出的结论是: c [ i ] c[i] c[i] 的值是索引 i i i 后面离它最近的与 s [ i ] s[i] s[i] 同字符的距离,然后数组c的后缀数组就等价于这个B函数生成的后缀数组。
  • 我们发现,按照B数组的生成方式,在已有后缀的前面加一个字母会引起后缀的变化,比如 B ( a b ) = 00 B(ab) = 00 B(ab)=00,而 B ( a a b ) = 010 B(aab) = 010 B(aab)=010 ,但是我们计算的C数组,前面加字母就不会出现这种问题。
  • 这个题的C数组又变化了一下。记录的是 N - c[i] 的值,然后直接后缀数组排序,就是答案。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int C[maxn];
char str[maxn];
//rk[i] 表示下标为i开头后缀的排名
//sa[i] 表示第i小的后缀首字母对应原字符串下标。
int rk[maxn], sa[maxn], tmp[maxn];
int N, k;
bool cmp(int i, int j)
{
    if(rk[i] != rk[j]) return rk[i] < rk[j];
    else{
        int ri = i + k <= N ? rk[i + k] : -1;
        int rj = j + k <= N ? rk[j + k] : -1;
        return ri < rj;
    }
}
//if s is a string, please use: get_sa(char s[], int sa[])
void get_sa(int S[], int sa[])
{
    for(int i = 0; i <= N; i++){
        sa[i] = i;
        rk[i] = i < N ? S[i] : -1;
    }
    for(k = 1; k <= N; k <<= 1){
        sort(sa, sa + N + 1, cmp);
        tmp[sa[0]] = 0;
        for(int i = 1; i <= N; i++){
            tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
        }
        for(int i = 0; i <= N; i++){
            rk[i] = tmp[i];
        }
    }
}
int main()
{
    while(cin >> N){
        scanf("%s", str);
        int a = N, b = N;
        for(int i = N - 1; i >= 0; i--){
            if(str[i] == 'a'){
                if(a == N) C[i] = 0;
                else C[i] = (N - a + i) % N;
                a = i;
            }
            else{
                if(str[i] == 'b'){
                    if(b == N) C[i] = 0;
                    else C[i] = (N - b + i) % N;
                    b = i;
                }
            }
        }
        get_sa(C, sa);
        for(int i = 1; i <= N; i++){
            printf("%d%c", sa[i] + 1, i == N ? '\n' : ' ');
        }
    }
    return 0;
}

F. Infinite String Comparision

  • 题意:在这里插入图片描述
  • 标解给了一个很奇妙的性质:两个字符串 s 1 s_1 s1, s 2 s_2 s2,第一个长度为 a,第二个长度为 b,那么如果两个字符串 s 1 ∞ , s 2 ∞ s_1^\infty, s_2^\infty s1,s2,在 a + b − g c d ( a , b ) a + b - gcd(a, b) a+bgcd(a,b) 内无法比较字典序的大小,那么他们必然是相等的。
  • 提到的一个定理。Periodicity Lemma:假设一个字符串 S 有循环节 p 和 q 并且满足 p + q ≤ ∣ S ∣ + g c d ( p , q ) p + q \le |S| + gcd(p, q) p+qS+gcd(p,q),那么 gcd(p, q) 也是一个循环节。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
char s1[maxn], s2[maxn];
int main()
{
    ios::sync_with_stdio(false);
    while(cin >> s1 >> s2){
        int N = strlen(s1), M = strlen(s2);
        int g = __gcd(N, M);
        bool flag = false;
        for(int i = 0; i < N + M - g; i++){
            if(s1[i % N] > s2[i % M]){
                printf(">\n");
                flag = true;
                break;
            }
            else if(s1[i % N] < s2[i % M]){
                printf("<\n");
                flag = true;
                break;
            }
        }
        if(!flag) printf("=\n");
    }
    return 0;
}

不过这个题还有一个法二,就是比较 s 1 + s 2 s_1+s_2 s1+s2 s 2 + s 1 s_2 + s_1 s2+s1 作比较。我们举个例子,假如 l e n ( s 1 ) = 3 , l e n ( s 2 ) = 2 len(s_1) = 3, len(s_2) = 2 len(s1)=3,len(s2)=2,那么对于而且 s 1 [ 1 : 2 ] = = s 2 [ 1 : 2 ] s_1[1:2] == s_2[1:2] s1[1:2]==s2[1:2],那么我们接下来比较的就是 s 1 [ 3 ] s_1[3] s1[3] s 2 [ 1 ] s_2[1] s2[1]. 因为 s 1 [ 1 ] = = s 2 [ 1 ] s_1[1] == s_2[1] s1[1]==s2[1],因此相当于比较 s 2 [ 1 ] = = s 2 [ 3 ] s_2[1] == s_2[3] s2[1]==s2[3]. 这其实就是在比较 s 1 + s 2 s_1+s_2 s1+s2 的第三个字符与 s 2 + s 1 s_2 + s_1 s2+s1 的第三个字符。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string a, b;
    while(cin >> a >> b){
        if(a + b > b + a) puts(">");
        else if(a + b == b + a) puts("=");
        else puts("<");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值