非线性字符串数据结构串讲

书接去年,今天作业不想写了,滚过来写总结。顺便保留我刚略微学会的串串。

声明:作者由于水平不高,所以有些定理不能严谨证明,所以若是初学者请移步别处。

1.Trie树

定义

Trie树又叫字典树,是非常显然的一种字符串数据结构。

具体来说,我们如果手上有很多字符串,我们可以通过建一个Trie树来做一些简单的操作。

其构建过程可以看一下图,非常显然,本质就是把字符串的相同部分压缩一下。

比如我们对

复制代码
aa

aba

ba

caaa

cab

cba

cc

建一个Trie就长这样。

构建

图来自OI wiki

然后构建这块也挺简单的

代码

cpp 复制代码
int len,idx,cnt[N],tr[N][70];
ll getid(char c){
	if(c>='A'&&c<='Z') return c-'A';
	else if(c>='a'&&c<='z') return c-'a'+26;
	else return c-'0'+52;
}
void add(string s){
	len=s.size();
	s=' '+s;
	int p=0;
	for(int i=1;i<=len;i++){
		int id=getid(s[i]);
		if(!tr[p][id]) tr[p][id]=++idx;
		p=tr[p][id];
		cnt[p]++;
	}
}
ll ask(string s){
	len=s.size();
	s=' '+s;
	int p=0;
	for(int i=1;i<=len;i++){
		int id=getid(s[i]);
		if(!tr[p][id]) return 0;
		p=tr[p][id];
	}
	return cnt[p];
}

空间这块,最坏情况每个字符串的每个字符都要新开一个节点,所以空间开即可。

上一道例题

AT_arc219_a ARC219A Similarity

AT_arc219_a ARC219A Similarity

正难则反

这个比较困难

所以就把S串01翻转,那么就是找出一个串串使得不能与任何一个S串相同。

那你给这些反串建出Trie后,找一个还没有被经过的节点即可。

例题结束

与异或相关

其实我们的Trie树不只能在字符串上用

因为在我们眼里数是有二进制的,二进制我们就可以想到01串。

我们就可以把数字当做01串建Trie树

当我们遇到一些神秘有关异或的题目时,

我们一想Trie树,二想线性基

比如来道题,给定你一个序列和x值,让你从这个序列中选一个元素,使之其与x的异或值最大。

考虑异或的性质,二进制位上不同为一,相同为0。

所以我们对序列建Trie树,把给定的x二进制分解,从高往低位的贪心的尽可能与x当前位不同。就行了。

来一道有意思的应用

P5283 十二省联考 2019 异或粽子

题解

2.AC自动机

定义

AC自动机,由两部分构成Trie树和fail树。

AC自动机的本质上就是建出Trie树后连fail边。

这里我们给出fail边的定义。

在Trie树上,每一个节点表示一个字符串。

fail边指向这个节点所代表的字符串 最长的后缀 所代表的节点。

图例

example:

图来自OI wiki

比如这个Trie树

给他建fail边就应该是这样的

由于根节点代表的是空串,空串是任何字符串的后缀。

所以当你实在在Trie树上找不到后缀时,就直接无脑连根结点就可以啦。

然后AC自动机的功能这块,可以通过拿一个字符串在上面跑得到在自动机上他的所有子串,不管通过Trie边还是fail边。

代码

cpp 复制代码
int n,m,len,idx=1;
string s;
struct trie{
	int son[29],fail;
	int flag;
}t[N];
struct AC_automation{
	void build(string s){
		len=s.size(); s=' '+s;
		int p=0;
		for(int i=1;i<=len;i++){
			int v=s[i]-'a'+1;
			if(!t[p].son[v]) t[p].son[v]=++idx;
			p=t[p].son[v];
		}
		t[p].flag++;
	}
	void getfail(){
		queue<int> q;
		for(int i=1;i<=26;i++) if(t[0].son[i]) q.push(t[0].son[i]);
		while(!q.empty()){
			int p=q.front();
			q.pop();
			for(int i=1;i<=26;i++){
				int v=t[p].son[i];
				int faf=t[p].fail;
				if(!v){
					t[p].son[i]=t[faf].son[i];
					continue;
				}
				t[v].fail=t[faf].son[i];
				q.push(v);
			}
		}
	}
	ll ask(string s){
		len=s.size(); s=' '+s;
		int p=0; ll ans=0;
		for(int i=1;i<=len;i++){
			int v=s[i]-'a'+1;
			int k=t[p].son[v];
			while(k>1&&t[k].flag!=-1){
				ans+=t[k].flag,t[k].flag=-1;
				k=t[k].fail;
			}
			p=t[p].son[v];
		}
		return ans;
	}
	
}AC;

P9613 CERC2019 K==S

大意就是构造一个长度为N的串串,让你是这个串串不包含给出的禁用短语作为子串,求方案数。

多模匹配想到建AC自动机并建图,由于不能含某些子串,所以不能走到这些子串的节点以及能通过跳fail边到这些子串的地方。

发现N很大,直接DP不行。但是状态转移固定,所以使用矩阵乘法优化DP就好了。

3.后缀数组

其实有点跑题了,因为后缀数组是线性的,但是后缀数组比较困难所以就写在这里了

定义

性质

图文来自洛谷

代码

cpp 复制代码
string s;
int sa[N],c[N],x[N],y[N],height[N],rk[N];
namespace SA{
	void getsa(){
		for(int i=1;i<=n;i++)++c[x[i]=s[i]];
		for(int i=2;i<=m;i++)c[i]+=c[i-1];
		for(int i=n;i;i--)sa[c[x[i]]--]=i;
		for(int k=1;k<=n;k*=2){
			int num=0;
			for(int i=n-k+1;i<=n;i++)y[++num]=i;
			for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
			for(int i=1;i<=m;i++)c[i]=0;
			for(int i=1;i<=n;i++)++c[x[i]];
			for(int i=2;i<=m;i++)c[i]+=c[i-1];
			for(int i=n;i;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0;
			swap(x,y);
			x[sa[1]]=1;
			num=1;
			for(int i=2;i<=n;i++){
				x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
			}
			if(num==n)break;
			m=num;
		}
	}
	void getheight(){
		for(int i=1;i<=n;i++) rk[sa[i]]=i;
		int k=0;
		for(int i=1;i<=n;i++){
			if(rk[i]==1) continue;
			if(k) k--;
			int j=sa[rk[i]-1];
			while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;
			height[rk[i]]=k;
		}
	}
}
using namespace SA;

4.后缀自动机

相关推荐
z小猫不吃鱼1 小时前
03 Optimal Brain Surgeon 详解:Hessian 剪枝为什么有效?
算法·机器学习·剪枝
硕风和炜2 小时前
【LeetCode: 1301. 最大得分的路径数目 + DP】
java·算法·leetcode·动态规划·dp·记忆化搜索
用户99045017780092 小时前
做了一个AI诊断,参考倪海厦中医理论,科学养生
算法
努力中的编程者2 小时前
STL-vector的模拟实现
开发语言·c++·算法·stl·vector
MartinYeung52 小时前
[论文学习]SecureGate:通过令牌级门控学习何时安全地揭示PII-深度解析
学习·安全
东华万里2 小时前
第32篇 数据结构入门 单链表的增删查改实现
数据结构·链表
没文化的阿浩2 小时前
【C++】详解继承机制
开发语言·c++
weixin_400005603 小时前
RL-frenet-trajectory-planning-in-CARLA
人工智能·深度学习·算法·机器学习·自动驾驶
Keven_113 小时前
AcWing算法提高课思路速查:动态规划
算法·动态规划