1367D 1800
题意:给你一段字符串,你可以从中选取字母,然后一个长度为n的数组,每个数字表示对于某个字符串s来说,为大于当前字母的位置为i,abs(当前位置-i)之和,问你s的字符串,保证s存在
思路:对于s从最大的字母开始计算,因为最大即贡献肯定是0,然后计算这个字母对这个字符串每个位置的贡献,然后会出现第二大的字母,且值为0,依次递推下去就行,因为题目保证了存在s。具体可看代码实现。(有好多地方容易出错)
代码如下:
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
#define rep(i, a, n) for(int i = a; i <= n; i++)
#define per(i, a, n) for(int i = n; i >= a; i--)
#define IOS std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define fopen freopen("file.in","r",stdin);freopen("file.out","w",stdout);
#define fclose fclose(stdin);fclose(stdout);
const int inf = 1e9;
const ll onf = 1e18;
const int maxn = 1e5+10;
inline int read(){
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
inline void cf(){
int t = read();
while(t--){
char s[60], str[60];scanf("%s", s);
int sum[30], a[60];
for(int i = 0; i < 30; i++) sum[i]=0; //sum的初始化,不是宏定义
for(int i = 0; i < (int)strlen(s); i++) sum[s[i]-'a']++;
int n = read();
for(int i = 0; i < n; i++) a[i]=read();
int pos = 26, ans = n;
while(ans){
std::vector<int> v;
int cnt = 0;
for(int i = 0; i < n; i++) if(a[i]==0) cnt++, a[i]=-1, v.push_back(i);
// 当前a[i]==0计算之后要更改,不然会重复计算
for(int i = 0; i < n; i++){
if(a[i]>0){
for(int j = 0; j < cnt; j++){
a[i]-=abs(i-v[j]); // 这里是abs(i-v[j])
}
}
}
for(int i = pos-1; i >= 0; i--) if(sum[i]>=cnt){pos=i;break;} // i=pos-1,因为pos已经是用过的了
for(int i = 0; i < cnt; i++) str[v[i]]=pos+'a';
ans-=cnt; // 计数,当ans==0时,即表示所有的位置都更新完了
}
str[n]='\0'; // 最后加一个终止符号
printf("%s\n", str);
}
return ;
}
signed main(){
cf();
return 0;
}
字符串匹配算法解析

本文深入探讨了一种基于字符串匹配的算法,通过分析特定字符串与数组的对应关系,提出了一种有效的计算方法。该方法从最大字母开始计算其对字符串各位置的贡献,逐步递推至最小字母,确保了字符串的存在性和正确性。
484

被折叠的 条评论
为什么被折叠?



