D. Min Cost String
链接
https://codeforces.com/problemset/problem/1511/D
题目
思路
显然原题的意思就是长度为2的子串出现次数取C(2,x),那么我们只要保证每个字串出现的最平均就行。如果有k个字母,那么最多不同的子串有k*k个。所以我们就直接找到一个最小的母串,然后重复遍历就行。这里如何构建母串呢?可以采用dp[x][y]
表示有没有出现,然后利用双指针:i指向当前位置,j指向下一个的位置,初始时j等于i,然后循环遍历找到第一个没出现的子串。并添加计数器,当出现k*k-1
个子串的时候就退出循环,直接开始复制就行。因为剩下那个正好首尾相接
!!!这个点被卡了好久。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
#define IOS ios::sync_with_stdio(false), cin.tie(0) ,cout.tie(0)
using namespace std;
#define int long long
bool dp[27][27];
signed main()
{
IOS;
int n, k;
cin >> n >> k;
string s;
s += '1';
int already = 0;
string sx;
for (int i = 1; i < n; i++)
{
if (already == k*k - 1)//计数器
{
break;
}
int j = s[i - 1] - '0';
while (dp[s[i - 1] - '0'][j]) { j = (j + 1) % k; if (!j)j = k; }//循环遍历
already++;
dp[s[i - 1] - '0'][j] = 1;//标记
char x = j + '0';
s += x;
}
for (int i = 0; i < n; i++)
{
int x = s[i % s.length()] - '0';
char xx = x + 'a' - 1;
cout << xx;
}
return 0;
}