题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222
题目大意:给n个模板串,求长串中模板串的个数;
解题思路:
自动机入门题,注意模板重复串。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<string> #include<queue> #include<deque> #include<stack> #include<map> #include<set> #define INF 0x7fffffff #define SUP 0x80000000 #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long LL; const int N=100007; /******************auther:ACsorry******************/ struct Trie{ Trie *next[26]; Trie *fail; int flag; Trie(){ mem(next,0); fail=0; flag=0; } }; int tot; Trie *p[500007]; Trie* newTrie() { p[tot]=new Trie(); tot++; return p[tot-1]; } void sInsert(Trie *root,char *s) { int i=0; Trie *p=root; while(s[i]){ int idx=s[i]-'a'; if(p->next[idx]==NULL){ p->next[idx]=newTrie(); } p=p->next[idx]; i++; } p->flag++; } void buildAc(Trie *root) { queue<Trie*> que; que.push(root); while(!que.empty()){ Trie *cur=que.front(); que.pop(); for(int i=0;i<26;i++){ if(cur->next[i]){ if(cur==root) cur->next[i]->fail=root; //第一个元素匹配 else{ Trie *p=cur->fail; while(p){ //搜索匹配 if(p->next[i]){ cur->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) cur->next[i]->fail=root; //匹配为空,从头开始 } que.push(cur->next[i]); } } } } int solve(Trie *root,char *s) { int ret=0; int len=strlen(s); Trie *p=root; for(int i=0;i<len;i++){ int idx=s[i]-'a'; while(p->next[idx]==NULL&&p!=root) p=p->fail; p=p->next[idx]; if(p==NULL) p=root; Trie *tmp=p; //ret+=(以p为后缀的串) while(tmp!=root&&tmp->flag!=-1){ ret+=tmp->flag; tmp->flag=-1; tmp=tmp->fail; } } return ret; } char s[1000007]; int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); Trie *root=newTrie(); for(int i=0;i<n;i++) { scanf("%s",s); sInsert(root,s); } buildAc(root); scanf("%s",s); printf("%d\n",solve(root,s)); for(int i=0;i<tot;i++) delete p[i]; } return 0; }
时间: 2024-11-08 19:19:33