1 5 she he say shr her yasherhs
3
题意:
多模板匹配问题。给你n个模板串和一个文本串。问你有几个模板串在文本串中出现过。
思路:
这题有个陷阱。就是模板串会给你重复的!巨坑!而且要把它们当不同的串处理!也就是输入了几次就算几个串。
所以用val记录单词出现次数就好。匹配一次后就把val归0.用ans统计。
详细见代码:
#include <iostream> #include<queue> #include<map> #include<string.h> #include<stdio.h> using namespace std; const int md=500110; const int ssz=26; const int maxn=1000010; char txt[maxn]; char words[60]; int ch[md][ssz],val[md],f[md],last[md]; int sz,ans; void init() { sz=1; val[0]=0; memset(ch[0],0,sizeof ch[0]); } int idx(char c) { return c-'a'; } void inser(char *s,int v) { int u=0,n=strlen(s); for(int i=0; i<n; i++) { int c=idx(s[i]); if(!ch[u][c]) { memset(ch[sz],0,sizeof ch[sz]); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]++;//同一单词可以多次计算。。。坑啊。。。 } void solve(int j) { if(j) { if(val[j]) { ans+=val[j]; val[j]=0; } solve(last[j]); } } void getf() { queue<int> q; int u,v,c,r; f[0]=0; for(c=0;c<ssz;c++) { u=ch[0][c]; if(u) { f[u]=0; q.push(u); last[u]=0; } } while(!q.empty())//bfs获取失配数组 { r=q.front(); q.pop(); for(c=0;c<ssz;c++) { u=ch[r][c]; if(!u) { ch[r][c]=ch[f[r]][c];//直接增加失配边 continue; } q.push(u); v=f[r]; while(v&&!ch[v][c]) v=f[v]; f[u]=ch[v][c]; last[u]=val[f[u]]?f[u]:last[f[u]]; } } } void findm(char *T) { int n=strlen(T),c,i,j=0; getf();//获得失配函数 for(i=0;i<n;i++) { c=idx(T[i]); //while(j&&!ch[j][c]) // j=f[j]; j=ch[j][c];//沿着边走就行 if(val[j]) solve(j); else if(last[j]) solve(last[j]); } } int main() { int i,t,n; scanf("%d",&t); while(t--) { init(); ans=0; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%s",words); inser(words,i); } scanf("%s",txt); findm(txt); printf("%d\n",ans); } return 0; } /* 1 h hhhhh 2 a a a */ /* 1 2 */