AC自动机
题目要求:输入n个单词,然后输入一段字符串,请问字符串中第几个位置第一次出现了该单词。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> using namespace std; char str[1010][100]; int ans; struct Trie { int next[1010*50][258],fail[1010*50],end[1010*50]; int root,L; int newnode() { for(int i = 0;i < 258;i++) next[L][i] = -1; end[L++] = -1; return L-1; } void init() { L = 0; root = newnode(); } void insert(char s[],int id) { int len = strlen(s); int now = root; for(int i = 0;i < len;i++) { if(next[now][s[i]] == -1) next[now][s[i]] = newnode(); now = next[now][s[i]]; } end[now] = id; } void build() { queue<int>Q; fail[root] = root; for(int i = 0;i < 128;i++) if(next[root][i] == -1) next[root][i] = root; else { fail[next[root][i]] = root; Q.push(next[root][i]); } while(!Q.empty()) { int now = Q.front(); Q.pop(); for(int i = 0;i < 258;i++) if(next[now][i] == -1) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } int num[1010]; void query(char buf[],int n) { int count=0; for(int i = 0;i < n;i++) num[i] = 0; int len=strlen(buf); int now=root; for(int i=0;i<len;i++) { if(buf[i]==' ') count++; now=next[now][buf[i]]; int temp = now; while( temp != root ) { if(end[temp] != -1&&num[end[temp]]==0) num[end[temp]]=count; temp = fail[temp]; } } for(int i = 0;i < n;i++) if(num[i] > 0) printf("%s: %d\n",str[i],num[i]); } }; char buf[2000010]; Trie ac; int main() { int n; while(scanf("%d",&n) == 1) { ans=0; ac.init(); getchar(); for(int i=0;i<n;i++) { gets(str[i]); ac.insert(str[i],i); } ac.build(); gets(buf); ac.query(buf,n); } return 0; }