专栏文章

题解:B4205 [常州市赛 2021] 特殊字符

B4205题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mint0ykg
此快照首次捕获于
2025/12/02 07:52
3 个月前
此快照最后确认于
2025/12/02 07:52
3 个月前
查看原文
这题直接每个特殊字符模拟出破译结果明显会超时。
发现题目只要求出第 kk 位,其他的字符都是没用的。
又发现每次复制出来的字符数是可以直接 O(1)O(1) 求出来的,而不参与复制的字符则就是只有一个字符不变。
所以对于每个特殊字符:遍历原来字符串,算出当前破译出的字符数量,如果超过了 kk 再具体通过取模求出具体字符。这样可以极大优化时间复杂度。
再具体点:对于每个特殊字符,遍历原字符串,对一每个遍历到的字符,执行一下操作。
  • 如果是特殊字符,计数器 cntcnt 加一,cntcnt 用来统计一段连续特殊字符的长度。
  • 如果不是特殊字符,且 cntcnt00,即不需要复制。则计数器 sumsum 加一。sumsum 表示当前这个已经遍历过的这个子串在破译后的长度。如果 sumsum 等于 kk 那么直接输出这个字符。
  • 如果不是特殊字符,且 cntcnt 不为 00,即要执行复制操作了。sumsum 要加上 min(ni,cnt)×cnt\min(n-i,cnt)\times cnt
  • 在上一条操作后如果 sumsum 大于等于 kk 了。提取出被复制的那段子串,记为 ss。先把 sumsum 还原成上一条操作加之前的值,接着输出 s(k(summin(ni,cnt)×cnt))modmin(ni,cnt)1s_{(k-(sum-\min(n-i,cnt)\times cnt))\mod \min(n-i,cnt)-1}。即 kk 超出的部分在复制后的串中对应位置的字符。不过这里要特判取模后为 00 的情况,以免出现 s1s_{-1}。 如果遍历完一直达到 kk 就输出 *
long long 哦。

code

CPP
#include<bits/stdc++.h>
using namespace std;
string a;
long long n,k;
void f(char c){
	long long cnt=0;
	long long sum=0;
	for(long long i=0;i<n;i++){
		if(a[i]==c){
			cnt++;
		}
		else{
			if(cnt!=0){
				sum+=min(n-i,cnt)*cnt;
				if(sum>=k){
					string s=a.substr(i,cnt);
					if((k-(sum-min(n-i,cnt)*cnt))%cnt==0){
						cout<<s[cnt-1];
					}
					else{
						cout<<s[(k-(sum-min(n-i,cnt)*cnt))%min(n-i,cnt)-1];
					}
					return;
				}
				i+=cnt-1;
				cnt=0;
			}
			else{
				sum++;
				if(sum==k){
					cout<<a[i];
					return;
				}
			}
		}
	}
	cout<<'*';
}
int main(){
	cin>>n>>k;
	cin>>a;
	for(char i='a';i<='z';i++){
		f(i);
	}
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...