您的位置:首页 > 其它

uva10679 I Love Strings!!

2018-01-11 09:31 387 查看
题面在这里

题意:

给你一个文本串和若干模式串,问每个模式串是否在文本串中出现过。

做法:

AC自动机模板题。对于重复的串的处理,可以在每个节点处挂一个链表记录模式串的编号。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<queue>
using namespace std;

const int N = 1000010, M = 52000010;
int n, cnt, tot;
char st
, s
;
int ans
, head[M], c
[55], fail[M], vis[M];
struct Linker{ int to, nxt; Linker() {}; Linker(int x, int y) { to = x, nxt = y; }; }e
;

inline int id(int x) { if(x >= 'a') return x-'a'+26; else return x-'A'; }
inline void link(int x, int y) { e[++ cnt] = Linker(y, head[x]); head[x] = cnt; }
inline void insert(char s[], int x)
{
int len = strlen(s), o = 0;
for(int i = 0; i < len; i ++) {
int t = id(s[i]);
if(!c[o][t]) c[o][t] = ++ tot;
o = c[o][t];
}
link(o, x);
}
inline void build()
{
queue<int> q;
for(int i = 0; i < 52; i ++) if(c[0][i]) { fail[c[0][i]] = 0; q.push(c[0][i]); }
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = 0; i < 52; i ++)
if(c[u][i]) { fail[c[u][i]] = c[fail[u]][i]; q.push(c[u][i]); }
else c[u][i] = c[fail[u]][i];
}
}
inline void cal(int x) { for(int i = head[x]; i; i = e[i].nxt) ans[e[i].to] = 1; }
inline void query(char s[])
{
int len = strlen(s), o = 0;
for(int i = 0; i < len; i ++) {
int t = id(s[i]); o = c[o][t];
for(int j = o; !vis[j]; j = fail[j]) cal(j), vis[j] = 1;
}
}
int main()
{
int Test; scanf("%d", &Test);
while(Test --) {
scanf("%s%d", st, &n); tot = 0; cnt = 0; memset(head, 0, sizeof head);
memset(c, 0, sizeof c); memset(fail, 0, sizeof fail);
memset(ans, 0, sizeof ans);
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i ++) {
scanf("%s", s);
insert(s, i);
}
build();
query(st);
for(int i = 1; i <= n; i ++) puts(ans[i]?"y":"n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: