nxt

E. Tree-String Problem (AC自动机+fail树)

最后都变了- 提交于 2020-01-29 09:01:17
https://codeforces.com/problemset/problem/291/E 题意:给你一颗树,然后每一条边有一个字符串,然后给你一个字符串,问这个字符在所有的树的根到叶子结点练成的串中,出现了多少次。 做法:建立AC自动机,每个点进行计数,在对询问串建AC自动机时不需要计数,然后dfs遍历fail树进行计数就可以了。 # include "bits/stdc++.h" using namespace std ; typedef long long ll ; const int maxn = 300000 + 10 ; const ll mod = 1000000000 + 7 ; # define lowbit(x) x&-x int nxt [ maxn ] [ 26 ] , fail [ maxn ] , sum [ maxn ] , tot ; int modify ( string s , int now , int f ) { int len = s . size ( ) ; for ( int i = 0 ; i < len ; i ++ ) { int id = s [ i ] - 'a' ; if ( nxt [ now ] [ id ] == 0 ) nxt [ now ] [ id ] = ++ tot ; now = nxt [ now ]

洛谷P3375 【模板】KMP字符串匹配

China☆狼群 提交于 2020-01-28 04:56:49
题目传送门: 戳我进入 KMP算法是用来处理字符串匹配的问题的,也就是给你两个字符串,你需要回答B串是否是A串的子串,B串在A串中出现了几次,B串在A串中出现的位置等问题。 KMP算法的意义在于,如果你在洛谷上发了一些话,kkksc03就可以根据KMP算法查找你是否说了一些不和谐的字,并且屏蔽掉你的句子里的不和谐的话( 比如cxk鸡你太美就会被屏蔽成cxk**** ),还会根据你句子中出现不和谐的字眼的次数对你进行处罚 举个栗子:A:GCAKIOI B:GC ,那么我们称B串是A串的子串 我们称等待匹配的A串为主串,用来匹配的B串为模式串。 一般的朴素做法就是枚举B串的第一个字母在A串中出现的位置并判断是否适合,而这种做法的时间复杂度是O(mn)的,当你处理一篇较长文章的时候显然就会超时。 我们会发现在字符串匹配的过程中,绝大多数的尝试都会失败,那么有没有一种算法能够利用这些失败的信息呢? KMP算法就是 KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的 设主串(以下称为T) 设模式串(以下称为W) 用暴力算法匹配字符串过程中,我们会把T[0] 跟 W[0] 匹配,如果相同则匹配下一个字符,直到出现不相同的情况,此时我们会丢弃前面的匹配信息,然后把T[1] 跟 W[0]匹配,循环进行,直到主串结束,或者出现匹配成功的情况

浅谈序列自动机

二次信任 提交于 2020-01-24 18:44:29
简介 序列自动机是一个可以快速判断字符串 \(t\) 是否是字符串 \(s\) 的子串的一个算法。 构造 对 \(s\) 构造序列自动机,使用 \(Nxt_{i,j}\) 代表从第 \(i\) 个位置开始,字符 \(j\) 出现的第一个位置。我们倒着遍历更新即可。 int nxt[N][27]; void init(char *s){ int l=strlen(s); for(int i=0;i<26;i++) nxt[l][i]=INF; for(int i=l-1;i>=0;i--){ for(int j=0;j<26;j++){ nxt[i][j]=nxt[i+1][j]; } nxt[i][s[i]-'a']=i; } } 查询 设置初始指针 \(p\) 为-1,每次让 \(p\) 跳到 \(Nxt_{p+1,j}\) 上面, \(j\) 为当前查询的字符,如果 \(p\) 为 \(INF\) ,则说明找不到下一个字符,即 \(t\) 不是 \(s\) 的子串。 bool find(char *t){ int pos=-1; int l=strlen(t); for(int i=0;i<l;i++){ pos=nxt[pos+1][t[i]-'a']; if(pos==INF) return 0; } return 1; } 模板 struct sub_AM{ int

POJ 3461 Oulipo (KMP)

ⅰ亾dé卋堺 提交于 2020-01-22 23:57:41
传送门 题目大意 有n次询问,问W串在T串中出现的次数 题解 KMP 代码 #include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,lenw,lent,nxt[10009]; char w[10009],t[1000009]; void getnext(){ for(int i=2,j=0;i<=lenw;i++){ while(w[i]!=w[j+1]&&j)j=nxt[j]; if(w[i]==w[j+1])nxt[i]=++j; } } int kmp(){ int js=0; for(int i=1,j=0;i<=lent;i++){ while(t[i]!=w[j+1]&&j)j=nxt[j]; if(t[i]==w[j+1])j++; if(j==lenw){js++;j=nxt[lenw];} } return js; } int main(){ scanf("%d",&n); while(n--){ scanf("%s\n%s",w+1,t+1); lenw=strlen(w+1);lent=strlen(t+1); getnext(); printf("%d\n",kmp()); } return 0; } 来源: https://www.cnblogs

Codeforces 1149 B - Three Religions

▼魔方 西西 提交于 2020-01-19 11:31:55
B - Three Religions 思路:dp dp[i][j][k]:a的前i个和b的前j个和c的前k个能构成的最前面的位置 删字符时状态不用改变,加字符时只会改变1*250*250个状态 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r //#define mp make_pair #define pb push_back #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdi pair<double, int> #define pdd pair<double, double>

AMPPZ2014

本秂侑毒 提交于 2020-01-16 14:53:37
[AMPPZ2014]The Lawyer 记录每天结束的最早的会议以及开始的最晚的会议即可。 #include<cstdio> #define N 500010 int n,m,i,d,a[N],b[N],st[21],en[21]; inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} int main(){ for(read(n),read(m),i=1;i<=n;i++){ read(a[i]),read(b[i]),read(d); if(!en[d]||b[en[d]]>b[i])en[d]=i; if(!st[d]||a[st[d]]<a[i])st[d]=i; } for(i=1;i<=m;i++)if(!st[i]||b[en[i]]>=a[st[i]])puts("NIE");else printf("TAK %d %d\n",en[i],st[i]); return 0; }    [AMPPZ2014]Petrol 一遍spfa求出d[x]表示离x最近的加油站到x的距离。 对于每条边(x,y,w),将边权重置为d[x]+d[y]+w。

平衡树(splay)学习笔记

送分小仙女□ 提交于 2020-01-15 13:12:30
Splay和一般的BST的区别大概就是:每次插入一个元素后,把它旋转到根 其核心操作就是$splay$和$rotate$ Rotate:把$x$转到$x$的父亲的位置上   $rotate$很好理解,自己画个图玩玩就会了, 代码要注意细节 void pushup(int x) { sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x]; } void rotate(int x) { int y=fa[x],z=fa[y],k=(x == ch[y][1]); if(z) ch[z][y == ch[z][1]]=x; fa[x]=z; ch[y][k]=ch[x][k^1], fa[ch[x][k^1]]=y; ch[x][k^1]=y, fa[y]=x; pushup(y); pushup(x); } Splay:把$x$转到目标$goal$的儿子的位置上(若$goal=0$,则把$x$转到根节点)   分三种情况:     1.$x$与$x$的父亲所属的儿子的种类相同(例如$x$是$y=fa[x]$的左儿子,$fa[x]$是$z=fa[fa[x]]$的左儿子)     2.与上面一种相反     3.$fa[fa[x]]=goal$   对于第一种情况,先把$y$转到$z$,再把$x$转到$y$   对于第二种情况,把$x$一路转上去   对于第三种情况

扩展KMP模板

送分小仙女□ 提交于 2020-01-14 04:48:54
具体原理可以参考这里: 扩展KMP 、 扩展KMP算法(刘毅) 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=1e6+5; 7 8 int len1,len2; 9 int nxt[N],extend[N]; //nxt[i]表示t[0...len2-1]和t[i...len2-1]的最大公共前缀长度 10 //extend[i]表示s[i...len1-1]和t[0...len2-1]的最大公共前缀长度 11 12 //获得next[i](0<=i<=len(t)),跟ex_kmp()类似,相当于字符串自身t匹配,t[i..len2-1]和t[0...len2-1]和等价于s和t 13 void getnext(char *t){ 14 int a,p,len; 15 len=strlen(t); 16 nxt[0]=len; 17 for(int i=1,j=-1;i<len;i++,j--){ 18 if(j<0||i+nxt[i-a]>=p){ 19 if(j<0) 20 p=i,j=0; 21 while(p<len&&t[p]==t[j]) 22 p++,j++; 23

P5840 [COCI2015]Divljak【AC自动机+fail树+树上乱搞】

泄露秘密 提交于 2020-01-10 06:23:28
https://www.luogu.com.cn/problem/P5840 题意:中文题,给你n个串,然后m次操作,两种操作。 1操作,集合T加入一个串。2操作,询问集合T中出现上面的n个串的第i个几次。 首先听说解法挺多的,如果有幸学会了,后来补上吧。 做法:这里用AC自动机做吧,首先对n个串建立AC自动机,建立fail树,然后每一次往T集合中加入一个字符串,就让他到AC自动机中跑,跑到的点对应到fail树上点到根上的串表示都出现了,但不过一次加入中只每个点最多只能加1,因此需要去重,同时对于同一条链上点,需要利用DFS序加LCA处理一下。统计的时候就用树状数组吧。 下面这份代码可能写丑了,不开O2勉强卡过去。 # include "bits/stdc++.h" using namespace std ; inline int read ( ) { int x = 0 ; bool f = 1 ; char c = getchar ( ) ; for ( ; ! isdigit ( c ) ; c = getchar ( ) ) if ( c == '-' ) f = 0 ; for ( ; isdigit ( c ) ; c = getchar ( ) ) x = ( x << 3 ) + ( x << 1 ) + c - '0' ; if ( f ) return x ;

Codeforces Round #612 (Div. 2)

让人想犯罪 __ 提交于 2020-01-06 15:39:01
https://codeforces.com/contest/1287/ A - Angry Students 题意:求A后面的P最长连续有几个? 题解:? int n; char s[200005]; void test_case() { scanf("%d%s", &n, s + 1); int cnt = 0, ans = 0; int b = 1; while(b <= n && s[b] == 'P') ++b; for(int i = b; i <= n; ++i) { if(s[i] == 'P') ++cnt; else { ans = max(ans, cnt); cnt = 0; } } ans = max(ans, cnt); printf("%d\n", ans); } 一种不需要判断结尾的思路是,一边统计cnt,一边尝试更新ans。 B - Hyperset 题意:每个属性只有3种值。定义三张牌是一个SET,当他们每个属性要么全等要么两两不同。 题解:枚举两张牌,可以确定第三张牌。 struct TrieNode { int data; int nxt[3]; void Init() { data = 0; memset(nxt, 0, sizeof(nxt)); } }; struct Trie { static const int MAXN =