"蔚来杯"2022牛客暑期多校训练营3 题解
C. Concatenation
原题https://www.luogu.com.cn/problem/P1012
直接排序略卡常
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int MAXN = (int)2e6 + 5;
string S[MAXN];
int n;
bool cmp(const string &a, const string &b) {
string c1 = a + b, c2 = b + a;
for(int i = 0; i < c1.length(); i++) {
if(c1[i] > c2[i]) return 0;
else if(c1[i] < c2[i]) return 1;
}
return 0;
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++) cin >> S[i];
sort(S + 1, S + 1 + n, cmp);
for(int i = 1; i <= n; i++) cout << S[i];
return 0;
}
J. Journey
将每条边(正向和反向)转换成点,跑一个4e6的最短路或BFS即可。这边用双端队列优化的Dijkstra实现。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
const int MAXN = 5e5 + 5;
const int INF = 0x3f3f3f3f;
struct Node {
int u, w;
bool operator < (const Node &a) const { return w > a.w; }
};
int n, c[MAXN][5], cnt, s1, s2, t1, t2, vis[MAXN << 3], dist[MAXN << 3];
unordered_map<int, int> Map[MAXN];
deque<Node> Q;
vector<Node> G[MAXN << 3];
inline void read(int &X) {
X = 0; int w = 0; char ch = 0;
while(!isdigit(ch)) w |= ch=='-', ch = getchar();
while( isdigit(ch)) X = (X<<3)+ (X<<1) + (ch-48), ch = getchar();
X = w ? -X : X;
}
void Dijkstra(int s) {
for(int i = 1; i <= cnt; i++) vis[i] = 0, dist[i] = INF;
dist[s] = 0;
Q.push_back({s, 0});
while(!Q.empty()) {
Node now = Q.front();
int u = now.u, w = now.w;
Q.pop_front();
if(vis[u]) continue;
vis[u] = 1;
for(auto i : G[u]) {
int v = i.u, w = i.w;
if(dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
if(w) Q.push_back({v, dist[v]});
else Q.push_front({v, dist[v]});
}
}
}
}
signed main()
{
//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
read(n);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= 4; ++j) {
read(c[i][j]);
if(!c[i][j]) continue;
int u = i, v = c[i][j];
if(!Map[u][v]) Map[u][v] = ++cnt;
if(!Map[v][u]) Map[v][u] = ++cnt;
}
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= 4; ++j) {
for(int k = 1; k <= 4; ++k) {
int u = c[i][j], v = i, w = c[i][k], cost;
cost = !(k == j % 4 + 1);
G[ Map[u][v] ].push_back( {Map[v][w], cost} );
}
}
}
read(s1); read(s2); read(t1); read(t2);
Dijkstra(Map[s1][s2]);
if(dist[ Map[t1][t2] ] >= INF) dist[ Map[t1][t2] ] = -1;
cout << dist[ Map[t1][t2] ];
return 0;
}
H. Hacker
先对A串建立SAM,对每个B串在A串中跑后缀自动机。
① 若自动机上没有对应节点则回到起始状态,当前sum为0
② 若自动机上有对应节点,但加上对应权值后sum小于0,处理情况同①
③ 若自动机上有对应节点,且加上对应权值后sum大于等于0,将当前状态移到此节点并更新sum
最后求出遍历B串时,所有sum的最大值。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
#define pir make_pair
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
const int MAXN = 4e5 + 5;
const int MOD = 1e9 + 7;
const int INF = 1e18;
string S;
int n, m, k, a[MAXN];
struct SAM {
int sz = 1, last = 1;
struct state {
int len, link, size;
map<char, int> next;
}st[MAXN << 1];
void Init() {
st[0].len = 0;
st[0].link = -1;
sz++;
last = 0;
}
void Extend(char c) {
int cur = sz++;
st[cur].size = 1;
st[cur].len = st[last].len + 1;
int p = last;
while(p != -1 && !st[p].next.count(c)) {
st[p].next[c] = cur;
p = st[p].link;
}
if(p == -1) st[cur].link = 0;
else {
int q = st[p].next[c];
if(st[p].len + 1 == st[q].len) st[cur].link = q;
else {
int clone = sz++;
st[clone].len = st[p].len + 1;
st[clone].next = st[q].next;
st[clone].link = st[q].link;
while(p != -1 && st[p].next[c] == q) {
st[p].next[c] = clone;
p = st[p].link;
}
st[q].link = st[cur].link = clone;
}
}
last = cur;
}
}sam;
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m >> k >> S;
sam.Init();
for(auto i : S) sam.Extend(i);
for(int i = 0; i < m; i++) cin >> a[i];
while(k--) {
string T; cin >> T;
int u = 0, sum = 0, maxx = 0;
for(int i = 0; i < m; i++) {
int nxt = sam.st[u].next[ T[i] ];
if(sum + a[i] >= 0 && nxt) sum += a[i], u = nxt;
else u = 0, sum = 0;
maxx = max(maxx, sum);
}
cout << maxx << "\n";
}
return 0;
}

浙公网安备 33010602011771号