[XSY] 字符串题(字符串,构造)

字符串题

  • 考虑找到一种方法,能够对一个 lyndon 串 A ,直接求出 A 的下一个 lyndon 串。
  • 考虑不断复制 A ,得 AAA…A
  • 因为 lyndon 串是自身循环移位得到的串中字典序严格最小的,所以 AAA…A 非lyndon 串。
  • 考虑微调:将 AAA…A 的末尾稍变大一些。具体方法如下:
    1.若 AAA…A 的最后一位不为 ‘a’+m-1,让 AAA…A 的最后一个字符变为这个字符在字符集中的后继(如a变成b,b变成c)
    2.若 AAA…A 的最后一位为 ‘a’+m-1,删去最后一位,一直删到最后一位不为 ′a′+m−1 为止,然后按1.的情况处理
    (ps.其实就是找字典序比A大一的字符串A’,这样得到的串 AA…AA’ 字典序刚好比 AAA…A 大一)
  • 可以证明 AA…AA’ 为 lyndon 串 :

若循环移位后的串以A开头:
则必有A…AA’A…A>AAA…AA’。

若循环移位后的串不以A开头:
A = a 1 a 2 ⋯ a ∣ A ∣ A=a_1a_2⋯a_{|A|} A=a1a2aA
由于 A 为 lyndon 串,所以对 ∀ 1 < i ≤ ∣ A ∣ ∀1<i≤|A| 1<iA ,有 a i a i + 1 ⋯ a ∣ A ∣ a 1 a 2 . . . a i − 1 > a 1 a 2 ⋯ a ∣ A ∣ a_ia_{i+1}⋯a_{|A|}a_1a_2...a_{i-1}>a_1a_2⋯a_{|A|} aiai+1aAa1a2...ai1>a1a2aA 。所以得到的串字典序必大于 AA…AA’

  • 考虑怎么让 AA…AA’ 与 A 之间无其它 lyndon 串:
    设 T 为 A 与 AA…AA’ 之间的一个 lyndon 串。因为 A<T<AA…AA’,所以有T=AA…AT’,其中T’ 的前 |A| 位不等于 A。

若 T 中A循环部分的长度 <= AA…AA’ 中A循环部分的长度:
因为 AA…AT’<AA…AA’,所以 T’<=A ,则以 T′ 开头的循环移位小于等于 T ,与 T 是 lyndon 串矛盾

若 T 中A循环部分的长度 > AA…AA’ 中A循环部分的长度:
必有 A<T<AA…AA’,且根据之前的结论,只要令 T’>A,T 必为 lyndon 串

  • 也就是说我们必须令 T中A循环部分的长度 > AA…AA’ 中A循环部分的长度 的T 不符合条件,即|T|>n
  • 那么 AA…AA’ 必须尽可能地长,我们考虑不断复制 A,然后取 AAA… 的前n位,记为 S,再找到字典序比 S 大一的字符串即可(如上文所述)。
  • 可以证明这样得到的串是符合条件的
    证明
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Que{
    int x,id;
}que[200010];
int n,m,q,len;
char ans[200010][31],ch[31];
bool cmp(Que a,Que b){
    return a.x<b.x;
}
int main(){
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=q;i++){
        scanf("%d",&que[i].x);
        que[i].id=i;
    }
    sort(que+1,que+q+1,cmp);
    ch[len=1]='a';
    int p=1;
    for(int i=1;i<=q;i++){
        while(p<que[i].x){
            for(int j=len+1;j<=n;j++) ch[j]=ch[j-len];
            len=n;
            while(ch[len]=='a'+m-1) ch[len--]=0;
            ch[len]++;
            p++;            
        }
        for(int j=1;j<=len;j++) ans[que[i].id][j]=ch[j];
    }
    for(int i=1;i<=q;i++){
        for(int j=1;ans[i][j];j++) putchar(ans[i][j]);
        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值