1. 给出模式串和文本串,文本串长度小于1e6,模式串长度之和小于1e6,求文本串中有多少模式串出现。
题目链接:https://www.luogu.org/problem/P3808
AC code:
/* luoguP3808 (AC自动机模板题) 求文本串中有多少模式串出现 */ #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #include<cstdlib> using namespace std; const int maxn=1e6+5; struct Tree{ //Trie树 int fail,vis[30],key; //key用来记录有几个单词以这个节点结尾 }AC[maxn]; int n,cnt; char s[maxn]; //在Trie树中插入结点 void build(char *s){ int len=strlen(s),u=0; for(int i=0;i<len;++i){ int t=s[i]-‘a‘; if(!AC[u].vis[t]) AC[u].vis[t]=++cnt; u=AC[u].vis[t]; } AC[u].key+=1; } //构建fail指针 void get_fail(){ queue<int> que; for(int i=0;i<26;++i){ //提前处理第二层 if(AC[0].vis[i]){ AC[AC[0].vis[i]].fail=0; //指向根节点 que.push(AC[0].vis[i]); } } while(!que.empty()){ //bfs求所有子结点 int u=que.front(); que.pop(); for(int i=0;i<26;++i){ if(AC[u].vis[i]){ AC[AC[u].vis[i]].fail=AC[AC[u].fail].vis[i]; que.push(AC[u].vis[i]); } else{ AC[u].vis[i]=AC[AC[u].fail].vis[i]; } } } } //AC自动机匹配 int query(char *s){ int len=strlen(s),u=0,ans=0; for(int i=0;i<len;++i){ int t=s[i]-‘a‘; u=AC[u].vis[t]; for(int j=u;j&&AC[j].key!=-1;j=AC[j].fail){ //循环求解 ans+=AC[j].key; AC[j].key=-1; } } return ans; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%s",s); build(s); } AC[0].fail=0; //结束标志 get_fail(); //求失配指针 scanf("%s",s); printf("%d\n",query(s)); return 0; }
原文地址:https://www.cnblogs.com/FrankChen831X/p/11875749.html
时间: 2024-10-05 02:52:06