luogu P3808 【模板】AC自動機(簡單版)
阿新 • • 發佈:2017-11-25
重復 數組 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自動機(簡單版)