题意:给一个字符串,和n个单词,问出现过多少个单词。
思路:ac自动机模板题。注意每个单词只能被算一次
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std ; const int maxw = 26; const int maxn = 10005; const int time = 55; const int maxs = 1000003; struct DFAAC{ int tire[maxn*time][maxw]; int fail[maxn*time]; int tag[maxn*time]; bool vis[maxn*time]; int root ,P; int New(){ tag[P] = 0; for(int i=0;i<maxw;i++) tire[P][i] = 0; return P++; } void Init(){ P=0; root = New(); } void Insert(char ch[]){ int now = root; for(int i=0;ch[i];i++) { int &nxt = tire[now][ch[i]-'a']; if(nxt==0) nxt = New(); now = nxt; } tag[now]++; } void built(){ queue<int>Q; for(int i=0;i<maxw;i++){ int &x = tire[root][i]; if(x!=0){ Q.push(x); fail[x]=0; } } while(!Q.empty()){ int u = Q.front(); Q.pop(); for(int i=0;i<maxw;i++){ int &v = tire[u][i]; if(v){ fail[v] = tire[fail[u]][i]; // tag[u] += tag[fail[u]]; Q.push(v); } else v = tire[fail[u]][i]; } } } int quert(char ch[]){ memset(vis,0,sizeof(vis)); int ret = 0; int now = root; for(int i=0;ch[i];i++){ now = tire[now][ch[i]-'a']; int tmp = now; while(tmp!=0){ if(vis[tmp]) break; ret += tag[tmp]; vis[tmp] = 1; //tag[tmp] = 0; tmp = fail[tmp]; } } return ret; } }; char ch[maxs]; int n , t; DFAAC ac; int main() { scanf("%d",&t); while(t--){ scanf("%d",&n); ac.Init(); while(n--){ scanf("%s",ch); ac.Insert(ch); } ac.built(); scanf("%s",ch); printf("%d\n",ac.quert(ch)); } }