2022NOIPA层联测4

A 字符串还原

删去一个那么 \([1, n/2]\) \([n/2 + 1, n]\) 有一个不变

那么 \(check\) 一下就行了,

赛时理解错了 \(unique\) 挂了 \(20\)

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int maxn = 2000005;
char s[maxn];
int n;
bool fr = 1, delr = 0;
bool fl = 1, dell = 0;
int mid, len;
bool check(){
	for(int i = 1; i <= len; ++i)if(s[i] != s[mid + i])return true;
	return false;
}
int main(){
	scanf("%d%s",&n,s + 1);
	if(n % 2 == 0){
		printf("NOT POSSIBLE\n");
		return 0;
	}
	len = n >> 1;
	mid = len + 1;
	for(int i = 1; i <= len; ++i){
		if(s[i] != s[len + i + dell]){
			if(dell){fl = 0; break;}
			dell = 1; --i;
		}
	}
	for(int i = 1; i <= len; ++i){
		if(s[i + delr] != s[mid + i]){
			if(delr){fr = 0; break;}
			delr = 1; --i;
		}
	}
	if(!fl && !fr){
		printf("NOT POSSIBLE\n");
	}else if(fl && fr && check()){
		printf("NOT UNIQUE\n");
	}else{
		if(fl){ for(int i = 1; i < mid; ++i)printf("%c",s[i]);
		}else{ for(int i = mid + 1; i <= n; ++i)printf("%c",s[i]);}
	}
	return 0;
}

B 数环

不会,弃了

发现性质操作为交换前缀和

然后断环成链怎么搞,不会

image

C 所有可能

重学广义 \(sam\)

其实是求前面出现的所有子串次数的平方

然后建出 \(sam\) 对应的 \(parent\) 树,进行树剖

每次匹配一个串,在匹配的每个位置修改其到根的 \(endpos\) 集合

线段树维护其集合大小的平方乘上对应字符串数量 \(len - len_{fa}\)

多维护几个值来进行区间修改

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int maxn = 600005;

int head[maxn], tot;
struct edge{int to, net;}e[maxn];
int fa[maxn], son[maxn], top[maxn], size[maxn], dep[maxn], dfn[maxn], id[maxn];
void add(int u, int v){
	e[++tot].net = head[u];
	head[u] = tot;
	e[tot].to = v;
}
void dfs1(int x){
	size[x] = 1;
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to;
		fa[v] = x; dep[v] = dep[x] + 1;
		dfs1(v);
		size[x] += size[v];
		son[x] = size[son[x]] > size[v] ? son[x] : v;
	}
}
int tim;
void dfs2(int x, int tp){
	top[x] = tp; dfn[x] = ++tim; id[tim] = x;
	if(son[x])dfs2(son[x], tp);
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to;
		if(v == son[x])continue;
		dfs2(v, v);
	}
}
int cnt = 1, las = 1;
struct note{
	int ch[26], len, fa;
}d[maxn];
void insert(int c){
	if(d[las].ch[c]){
		int fa = las, x = d[las].ch[c];
		if(d[fa].len + 1 == d[x].len)las = x;
		else{
			int now = las = ++cnt;
			d[now] = d[x];
			d[now].len = d[fa].len + 1;
			for(; fa && d[fa].ch[c] == x; fa = d[fa].fa)d[fa].ch[c] = now;
			d[x].fa = now;
		}
	}else{
		int fa = las;
		int now = las = ++cnt;
		d[now].len = d[fa].len + 1;
		for(; fa && !d[fa].ch[c]; fa = d[fa].fa)d[fa].ch[c] = now;
		if(!fa)d[now].fa = 1;
		else{
			int x = d[fa].ch[c];
			if(d[fa].len + 1 == d[x].len)d[now].fa = x;
			else{
				int clone = ++cnt;
				d[clone] = d[x];
				d[clone].len = d[fa].len + 1;
				d[x].fa = d[now].fa = clone;
				for(; fa && d[fa].ch[c] == x; fa = d[fa].fa)d[fa].ch[c] = clone;
			}
		}
	}
}
struct seg{
	struct node{
		ll s, val, size, tag, mul;
	}t[maxn << 2 | 1];
	void push_up(int x){
		int ls = x << 1, rs = x << 1 | 1;
		t[x].s = t[ls].s + t[rs].s;
		t[x].val = t[ls].val + t[rs].val;
		t[x].size = t[ls].size + t[rs].size;
		t[x].mul = t[ls].mul + t[rs].mul;
	}
	void upd(int x, int l, int r, ll val){
		t[x].tag += val;
		t[x].val = t[x].val + 2 * t[x].mul * val + t[x].size * val * val;
		t[x].mul += t[x].size * val;
		t[x].s += (r - l + 1) * val;
	}
	void push_down(int x, int l, int r){
		int mid = (l + r) >> 1;
		upd(x << 1, l, mid, t[x].tag);
		upd(x << 1 | 1, mid + 1, r, t[x].tag);
		t[x].tag = 0;
	}
	void built(int x, int l, int r){
		if(l == r){
			t[x].size = d[id[l]].len - d[d[id[l]].fa].len;
			return;
		}
		int mid = (l + r) >> 1;
		built(x << 1, l, mid);
		built(x << 1 | 1, mid + 1, r);
		push_up(x);
	}
	void modify(int x, int l, int r, int L, int R){
		if(L <= l && r <= R){
			upd(x, l, r, 1);
			return;
		}
		if(t[x].tag)push_down(x, l, r);
		int mid = (l + r) >> 1;
		if(L <= mid)modify(x << 1, l, mid, L, R);
		if(R > mid)modify(x << 1 | 1, mid + 1, r, L, R);
		push_up(x);
	}
	ll qmax(){return t[1].val;}
}t;
void update(int x){
	while(x){
		t.modify(1, 1, cnt, dfn[top[x]], dfn[x]);
		x = fa[top[x]];
	}
}
char s[maxn], c[maxn];
int l[maxn], r[maxn], n;
void solve(int x){
	int now = 1;
	for(int i = l[x]; i <= r[x]; ++i){
		now = d[now].ch[s[i] - 'a'];
		update(now);
	}
	printf("%lld\n",t.qmax());
}
int main(){
	scanf("%d",&n);
	for(int i = 1; i <= n; ++i){
		scanf("%s",c + 1); int len = strlen(c + 1);
		l[i] = r[i - 1] + 1; r[i] = l[i] + len - 1;
		for(int j = 1; j <= len; ++j)s[j + r[i - 1]] = c[j];
		las = 1; for(int j = 1; j <= len; ++j)insert(c[j] - 'a');
	}
	for(int i = 2; i <= cnt; ++i)add(d[i].fa, i);
	dfs1(1); dfs2(1, 1); t.built(1, 1, cnt);
	for(int i = 1; i <= n; ++i)solve(i);
	return 0;
}

D 字符串生成

\(f_i\) 表示已经匹配了 \(i\) 位,到匹配 \(n\) 位的期望步数

\(f_i = 1 /2 f_{i + 1} +1 / 2 f_{trans_i} + 1\)

\(trans_i\)\(i + 1\) 失配到的位置

答案为 \(f_0\)

已知 \(f_n = 0\)

式子简单化一下用 \(i\) 代替 \(i + 1\)

\(f_i = 2f_ {i - 1}- f_{trans_{i - 1}} - 2\)

把所有 \(f_i\)\(f_0\)表示,用 \(f_n\) 解出来即可

\(trans\) 的求法,我这个比较玄学

有个 \(nxt_i = now\) 比较玄学,不加复杂度不对,加了正确性存在疑问,但是对拍拍不掉,有会的大佬可以解释下

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;


const int maxn = 1e6 + 55;
const int mod = 1e9 + 7;
char c[maxn];
int n, nxt[maxn], f[maxn];
int qpow(int x, int y){
	int ans = 1;
	for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1) ans = 1ll * ans * x % mod;
	return ans;
}
ll a[maxn], b[maxn];

int main(){
	scanf("%s",c + 1);
	n = strlen(c + 1);
	int las = 0;
	for(int i = 2; i <= n; ++i){
		while(las && c[las + 1] != c[i])las = nxt[las];
		if(c[las + 1] == c[i]) ++las;
		nxt[i] = las;
	}
	for(int i = 1; i < n; ++i){
		int now = nxt[i];
		while(now && c[now + 1] == c[i + 1])now = nxt[now];
		nxt[i] = now;
		if(c[now + 1] != c[i + 1])++now;
		f[i] = now;
	}
	a[0] = 1; b[0] = 0;
	for(int i = 1; i <= n; ++i){
		a[i] = (a[i - 1] + a[i - 1] - a[f[i - 1]]) % mod;
		b[i] = (b[i - 1] + b[i - 1] - b[f[i - 1]] - 2) % mod;
		a[i] = (a[i] % mod + mod) % mod;
		b[i] = (b[i] % mod + mod) % mod;
	}
	b[n] = mod - b[n];
	int ans = 1ll * b[n] * qpow(a[n], mod - 2) % mod;
	printf("%d\n",ans);
	return 0;
}
posted @ 2022-10-06 21:33  Chen_jr  阅读(26)  评论(0编辑  收藏  举报