1. 程式人生 > >luogu P3808 【模板】AC自動機(簡單版)

luogu P3808 【模板】AC自動機(簡單版)

重復 數組 max space length range spa truct ron

題目背景

這是一道簡單的AC自動機模板題。

用於檢測正確性以及算法常數。

為了防止卡OJ,在保證正確的基礎上只有兩組數據,請不要惡意提交。

管理員提示:本題數據內有重復的單詞,且重復單詞應該計算多次,請各位註意

題目描述

給定n個模式串和1個文本串,求有多少個模式串在文本串裏出現過。

輸入輸出格式

輸入格式:

第一行一個n,表示模式串個數;

下面n行每行一個模式串;

下面一行一個文本串。

輸出格式:

一個數表示答案

輸入輸出樣例

輸入樣例#1: 復制
2
a
aa
aa
輸出樣例#1: 復制
2

說明

subtask1[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6,n=1;

subtask2[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6;

終於A了,woc爽

TLE+RE的原因竟然是把數組開成char

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int  maxn = 1000004;
int n;
char s[maxn];
queue<int>que;
int ans=0;
struct Aho_Corasick_automaton {
    
int sz; char ch[maxn][26]; int val[maxn]; int last[maxn]; int fail[maxn]; int num; void init() { memset(ch[0],0,sizeof(ch[0])); sz=0; } void insert(char *s) { int len=strlen(s); int u=0; for(int i=0; i<len; ++i) {
int v=s[i]-a; if(!ch[u][v]) { val[sz+1]=0; ch[u][v]=++sz; } u=ch[u][v]; } //printf("%d\n",u); val[u]++; //printf("%d\n",val[1]); } void get_fail() { fail[0]=0; que.push(0); while(!que.empty()) { int u=que.front(); que.pop(); for(int i=0;i<26;i++) { int v=ch[u][i]; if(!v) { ch[u][i]=ch[fail[u]][i]; continue; } que.push(v); fail[v]=u ? ch[fail[u]][i]:0; last[v]=val[fail[v]] ? fail[v] : last[fail[v]]; } } } void find(char *s) { int len=strlen(s); int u=0; for(int i=0; i<len; i++) { int c=s[i]-a; u=ch[u][c]; // printf("%d\n",val[u]); if(val[u])ans+=val[u],val[u]=0; // printf("%d ***\n",ans); int v=u; while(last[v]) { v=last[v]; if(val[v])ans+=val[v],val[v]=0; } } } } ac; int main() { scanf("%d",&n); ac.init(); for(int i=1; i<=n; i++) { scanf("%s",s); ac.insert(s); } ac.get_fail(); scanf("%s",s); ac.find(s); //for(int i=1;i<=ac.sz;++i)printf("%d ",ac.val[i]); printf("%d\n",ans); return 0; }

luogu P3808 【模板】AC自動機(簡單版)