首页 > 其他分享 >洛谷P7469题解

洛谷P7469题解

时间:2023-05-05 09:45:28浏览次数:45  
标签:子串 cnt P7469 洛谷 int 题解 26 ind

题面

题意:有两个字符串 a 和 b,问 b 中有多少个本质不同子串可以由 a 删除若干个字符得到。
|a|,|b|<=3000


题解:字典树(这个题做法很多,后补)。
把字符串 b 的每个子串打到字典树上。
然后因为 3000^2*26 这个东西比较大,所以不能用 nxt[id][26] 来存储,于是使用链式前向星存图,这样 trie 就建出来了。
接下来考虑如何统计答案。因为要做的是本质不同子串,所以考虑如果 a 是

a.....b.....b

那么我在 a 之后接上第一个 b 肯定比接上第二个 b 优。就是说如果我取 a 的子串是 ab.... 那么这个 b 一定取得是前面那个 b。
这个证明不难。
所以说我对于每个位置去转移,只会考虑这个位置之后的第一个 a/b/c/.../z。
那就好办了。我存储每个位置之后的第一个 a/b/c/../z,然后如果字典树上做到了这个节点,同时能够向下转移的话就直接转移。转移每一位都意味着答案加一。

代码直接放上来以防文字太抽象

struct edge {
	int to, nxt, val;
} e[10000000];
int head[10000000], cnt, triecnt, n;
void add(int u, int v, int w) {
	e[++cnt].to = v;
	e[cnt].nxt = head[u];
	e[cnt].val = w;
	head[u] = cnt;
}
char a[4000], b[4000];
int ind[30], nxta[4000][30];
void insert(int x) {
	int p = 0;
	for(int i = x; i <= n; ++i) {
		int flag = 0;
		for(int j = head[p]; j; j = e[j].nxt) if(e[j].val == b[i] - 'a') {
			flag = 1;
			p = e[j].to;
			break;
		}
		if(!flag) {
			add(p, ++triecnt, b[i] - 'a');
			p = triecnt;
		}
	}
}
int ans;
void find(int u, int a) {
	for(int i = head[u]; i; i = e[i].nxt) if(nxta[a][e[i].val] != -1) {
		++ans;
		find(e[i].to, nxta[a][e[i].val]);
	}
}
int main() {
	ios::sync_with_stdio(0);
	scanf("%d%s%s", &n, a+1, b+1);
	memset(ind, -1, sizeof(ind));
	for(int i = n; i >= 0; --i) {
		for(int j = 0; j < 26; ++j) nxta[i][j] = ind[j];
		if(i) ind[a[i] - 'a'] = i;
	}
	for(int i = 1; i <= n; ++i) insert(i);
	find(0, 0);
	cout << ans;
	return 0;
}

标签:子串,cnt,P7469,洛谷,int,题解,26,ind
From: https://www.cnblogs.com/1358id/p/17373170.html

相关文章

  • 问题解答 | FMCW TDMA-MIMO毫米波雷达信号处理仿真
    本文编辑:@调皮连续波,保持关注调皮哥,获得更多雷达学习资料和建议!大家好,我是调皮哥,今天继续给大家分享干货,助力大家轻松、快乐、有方向地学习雷达。之前分享的文章:雷达仿真|FMCWTDMA-MIMO毫米波雷达信号处理仿真(可修改为DDMA-MIMO)当中,存在几个小问题(bug),具体如下:第十节:多普勒补偿”......
  • 关于容斥原理 / P5505题解
    发现很多题解连容斥原理的“钦定”和“至少”的区别都讲不清楚,误导萌新,所以写一下这两个东西的区别“钦定”这个东西是会算重的,而“至少”不会。举个例子吧,比如\(1\2\3\)三个位置不合法,如果我说“钦定”两个位置不合法,那么这里计算方案的时候这个不合法的方案会被计算三次,分......
  • [JOI 2016 Final]断层 题解
    题目链接首先发现斜着平移比较难处理,所以考虑将平面逆时针旋转\(45°\)。接着发现风化也不好处理,但是风化的一定不会作为答案,所以我们可以离线,然后倒着处理操作,上升变为下降。我们发现每个初始\(0\)点最后的坐标就是它正着做时初始的坐标,且每次操作都只会将连续一段点的\(......
  • 【23.05.03】好题题解
    好题题解A题目大意:计算一个项数为\(n\)的多项式除以\(x^3-x\)的余数多项式。数据范围:对于\(100\%\)的数据:\(2\leqn\leq2\times10^5\)解题分析:水题,直接多项式除法模拟即可。需要注意细节。ACCode:#include<bits/stdc++.h>usingnamespacestd;#d......
  • 【题解】ABC300 F,G
    F.MoreHolidays题目分析:考虑刻画一下我们选择是什么样子的。考虑我们最后选择的\(T\)中的一段一定是形如:一个完整的S选择一个后缀\(+\)若干个完整的S\(+\)一个完整的S的前缀。这样的话就启示我们直接枚举这个前后缀选择的是什么,然后就可以很快算出来了,但是枚举前......
  • [POI2005]SAM-Toy Cars 题解(贪心+堆)
    题面首先考虑一个贪心策略:当地板已经放满需要取出一个时,取下一次使用时间\(nxt\)最晚的那个。所以我们只需要一个可以快速求出一个集合中\(nxt\)最小的点并删除,插入新点的数据结构,这里很容易想到堆。代码很简洁,注意数组的下标是位置还是颜色(考场100pts到0pts)。code:......
  • Valhalla Siege 题解
    题目传送门一道二分题。先观察数据范围,\(1\len,q\le200,000\),显然需要\(O(n\logn)\)的复杂度。且\(1\lek_i\le10^{14}\),需要开longlong。我们需要二分到第一个血量大于伤害值的武士的位置,前面的武士都死了。而在C++算法库中,有一个函数upper_bound(底层原理是二分)正......
  • [蓝桥杯 2017 国 C] 合根植物 题解
    题目传送门一道并查集模板题。没什么好说的,先给个并查集模板,神犇可以直接跳过。查找根:intfind_root(intn){if(fa[n]==n)returnn;returnfa[n]=find_root(fa[n]);}合并:voidmerge(intx,inty){intsx=find_root(x),sy=find_root(y);......
  • Cashier 题解
    题目传送门一道贪心题。我们可以记录每一位客人离开的时间,当下一位客人来临时,他们之间空闲的时间就是我们休息的时间。for(inti=1;i<=n;i++){intt,l;cin>>t>>l;ans+=(t-endt)/a;endt=t+l;}最后再加上所有客人都走后的空闲时间......
  • [ABC213D] Takahashi Tour 题解
    题目传送门一道dfs序题。题目中高桥每次只会去最小的那个点,所以要先对整张图进行排序。for(inti=1;i<=n;i++)sort(g[i].begin(),g[i].end());然后考虑dfs。高桥不会走重复的点,所以我们可以开一个vis数组进行标记。然后我们需要处理高桥君如果无路可走会返回上......