"蔚来杯"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;
}
posted @ 2022-07-27 21:09  Orzjh  阅读(44)  评论(2)    收藏  举报