题目链接:http://poj.org/problem?id=4052
题目大意:北大还没把题目放出来,大意是给定n个字符串和一篇文章,求这些字符串中有几个在文章,如果某些字符串是某个字符串的字符串,那合起来只能算一个。最后输出含有的个数。
解题思路:这题在参加现场赛时根本就没看,不过当时也不一定做的出来,毕竟半年没做ac自动机了。这两天花了些时间把以前比赛未过的题目做了下,不做感觉那些被虐过的比赛还会一次一次的重演。凌晨时刻,人总是十分风骚,不说了,下面是思路:本题抛开含有子串这个约束就是裸ac自动机,现在有了这个约束可以三步走:1、把畸形字符串转化为正常字符串,题目有保证不管是畸形的还是正常的长度都有上限,用O(n)的复杂度转换下后面就简单了。2、建字典树,转换成Trie图,并把出现的串标记出来 3、利用Trie图把子串的标记去掉,最后统计下个数。
发现很多人写解题报告只贴代码,不给思路不给数据,看的我蛋疼,我就大发慈悲的给一坨数据吧。
测试数据:
100
8
B
CB
ACB
DACB
D
DA
DAC
DACB
DACB
3
A
B
C
ABCC
2
[2A]B
[3A]B
[5A]B[4A]B
2
AB
DCB
DABC
3
A
AB
ABC
DABC
3
AB
CD
EF
ABCDEF
26
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
ABCDEFGHIJKLMNOPQRSTUVWXYZ
代码:
#include <stdio.h>
#include <string.h>
#define MIN 6200000
#define MAX 4000000
struct node {
int flag,in;
node *fail,*next[26],*fa;
}*qu[MAX],arr[MAX],*root;
int n,m,ans,total,vis[3000];
char dir[2600][1200],temp[MIN],str[MIN];
node *CreateNode() {
node *p = &arr[total++];
p->flag = 0;
p->fail = p->fa = NULL;
for (int i = 0; i < 26; ++i)
p->next[i] = NULL;
return p;
}
void Insert(char *dir,int now) {
int i = 0,k;
node *p = root,*temp;
while (dir[i]) {
k = dir[i++] - 'A';
if (p->next[k] == NULL)
p->next[k] = CreateNode();
temp = p;
p = p->next[k];
p->fa = temp;
}
p->flag = 1,p->in = now;
}
void Build_AC() {
int head,tail,i;
head = tail = 0;
root->fail = root;
root->fa = root;
qu[++head] = root;
while (tail < head) {
node *p = qu[++tail];
for (i = 0; i < 26; ++i)
if (p->next[i] != NULL) {
if (p == root) p->next[i]->fail = root;
else p->next[i]->fail = p->fail->next[i];
qu[++head] = p->next[i];
}
else {
if (p == root) p->next[i] = root;
else p->next[i] = p->fail->next[i];
}
}
}
int Query_1A(char *str) {
int i,j,k;
i = ans = 0;
node *p = root,*temp;
while (str[i]) {
k = str[i++] - 'A';
p = p->next[k];
if (p->flag) vis[p->in] = 1;
}
for (i = 0; i < n; ++i) if (vis[i]) {
j = 0,p = root;
while (dir[i][j]) {
k = dir[i][j++] - 'A';
p = p->next[k];
}
temp = p->fa;
while (temp != root) {
if (temp->flag) {
vis[temp->in] = 0;
temp->flag = 0;
}
temp = temp->fa;
}
temp = p->fail;
while (temp != root) {
if (temp->flag) {
vis[temp->in] = 0;
temp->flag = 0;
}
temp = temp->fail;
}
}
for (i = 0; i < n; ++i)
if (vis[i]) ans++;
return ans;
}
void Decode(char *str){
int i = 0,j = 0,q,k,tpk;
while (str[i]) {
if (str[i] != '[')
temp[j++] = str[i++];
else {
for (q = 0,k = i + 1; str[k] >= '0' && str[k]<= '9'; ++k)
q = q * 10 + str[k] - '0';
for (tpk = 1; tpk <= q; ++tpk)
temp[j++] = str[k];
i = k + 2;
}
}
temp[j] = '\0';
strcpy(str,temp);
}
int main()
{
int i,j,k,t;
scanf("%d",&t);
while (t--) {
total = 0;
root = CreateNode();
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for (i = 0; i < n; ++i) {
scanf("%s",dir[i]);
Decode(dir[i]),Insert(dir[i],i);
}
scanf("%s",str);
Decode(str);
Build_AC();
ans = Query_1A(str);
printf("%d\n",ans);
}
return 0;
}
本文ZeroClock原创,但可以转载,因为我们是兄弟。