题目链接
ICPC2021沈阳站 E: Edward Gaming, the Champion
题意
输入一个字符串, 输出这个字符串中"edgnb"出现的次数。
题解
后缀自动机模板题。 将输入的字符串建立后缀自动机,从根节点开始沿 ->e->d->g->n->b 走。如果没有这个节点输出0。如果找到了这个节点,就输出这个节点endpos集合的大小。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 400000 + 100;
struct Node {
int len, fa;
int ch[26];
} node[maxn];
int es[maxn];
int idx = 1, last = 1;
char s[maxn];
int q[maxn], c[maxn];
void extend(int c) {
int p = last, np = ++idx;
es[np] = 1;
node[np].len = node[p].len + 1;
for(;p && !node[p].ch[c]; p = node[p].fa) {
node[p].ch[c] = np;
}
if(!p)
node[np].fa = 1;
else {
int q = node[p].ch[c];
if(node[q].len == node[p].len + 1) {
node[np].fa = q;
}else {
int nq = ++idx;
node[nq] = node[q];
node[nq].len = node[p].len + 1;
node[q].fa = node[np].fa = nq;
for(;p && node[p].ch[c] == q; p = node[p].fa)
node[p].ch[c] = nq;
}
}
last = np;
}
int main() {
scanf("%s", s);
int n = strlen(s);
for(int i = 0; i < n; i++)
extend(s[i] - 'a');
for(int i = 1; i <= idx; i ++)
c[node[i].len] ++;
for(int i = 1; i <= idx; i++)
c[i] += c[i - 1];
for(int i = idx; i >= 1; i--)
q[c[node[i].len]--] = i;
for(int i = idx; i >= 1; i--) {
int u = q[i];
es[node[u].fa] += es[u];
}
char T[] = "edgnb";
int cur = 1;
for(int i = 0; i < 5 && cur; i++)
cur = node[cur].ch[T[i] - 'a'];
es[0] = 0;
printf("%d\n", es[cur]);
return 0;
}
直接暴力也是可以过的
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
char s[N];
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
int ans=0;
for(int i=1;i<=n-4;i++){
if(s[i]=='e'&&s[i+1]=='d'&&s[i+2]=='g'&&s[i+3]=='n'&&s[i+4]=='b'){
ans++;
}
}
printf("%d\n",ans);
return 0;
}