HDU 3695:Computer Virus on Planet Pandora(AC自动机裸题,数组实现AC自动机)
2017-08-15 20:05
543 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3695
题目意思,给出n个模式串和一个文本串,求n个模式串在文本串正串,和反向串中出现的个数。
AC自动机裸题,把文本串在AC自动机上跑一遍,统计一下有多少模式串出现在正着的文本串,
然后将文本串逆序,再在AC自动机上跑一边,统计一下有多少模式串出现在反着的文本串。
不能用动态链表写,开始的时候用动态链表写,TLE了。静态链表没试过,不知道能不能过。
不过动态链表TLE后,我直接用数组写,活生生对着链表的代码改成数组形式的,差点没看晕过去。
不过完美AC了。
AC代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
const int allSon = 26;
int node[500000][allSon]; ///字典树节点
int fail[500000]; ///fail指针
int num[500000]; ///以某个节点结尾的单词数
char patten[1010]; ///用来存放模式串
char text[5100010]; ///用来存放文本串
char str[5100010];
int ans; ///放答案
int id; ///给节点编号
///将模式串插入到字典树
void insertPatten()
{
int p = 0;
int index = 0;
while(patten[index]!='\0')
{
int uppercase = patten[index]-'A';
if(node[p][uppercase]==-1) ///对应的儿子不存在
{
memset(node[id],-1,sizeof(node[id]));
num[id] = 0;
fail[id] = -1; ///fail指针置-1代表空
node[p][uppercase] = id++; ///相应的位置放置节点编号
}
p = node[p][uppercase];
index++;
}
num[p]++;
}
///找失败指针,构造AC自动机
void build_AC_automaton()
{
queue<int>qu;
int p = 0; ///最开始指向根节点
qu.push(p);
while(!qu.empty())
{
p = qu.front(); ///出队节点编号
qu.pop();
for(int i = 0; i < allSon; i++)
{
if(node[p][i] != -1) ///看看这个孩子存不存在
{
if(p==0) ///p是根节点
{
fail[node[p][i]] = 0; ///节点的fail指针指向根
}
else
{
int temp = fail[p];
while(temp != -1)
{
if(node[temp][i] != -1)
{
fail[node[p][i]] = node[temp][i];
break;
}
temp = fail[temp];
}
if(temp == -1)
{
fail[node[p][i]] = 0;
}
}
qu.push(node[p][i]);
}
}
}
}
///在AC自动机中进行多模式匹配
void find_in_AC_automaton()
{
int p = 0; ///根节点
int index = 0;
while(text[index]!='\0')
{
int uppercase = text[index]-'A';
while(node[p][uppercase]==-1 && p!=0)
p = fail[p];
p = node[p][uppercase];
if(p == -1) p = 0;
int temp = p;
while(temp!=0 && num[temp]!=-1)
{
ans += num[temp];
num[temp] = -1;
temp = fail[temp];
}
index++;
}
}
///输入文本串
void inputText()
{
scanf("%s",str);//puts(str);
int res = 0;
int pos = 0;
bool flag = false;
int len = strlen(str);
for(int i = 0; i < len; i++)
{
if(str[i]>='A' && str[i]<='Z')
{
if(flag)
{
while(res--)
{
text[pos++] = str[i];
}
}
else text[pos++] = str[i];
}
if(str[i]=='[') flag = true;
if(str[i]>='0' && str[i]<='9') res = res*10+(str[i]-'0');
if(str[i]==']')
{
res = 0;
flag = false;
}
}
text[pos] = '\0';///puts(text);
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(node[0],-1,sizeof(node[0])); ///0号节点是空节点
num[0] = 0;
fail[0] = -1;
id = 1;
for(int i = 0; i < n; i++)
{
scanf("%s",patten);
insertPatten();
}
inputText();
build_AC_automaton();
ans = 0;
find_in_AC_automaton();
int len = strlen(text);
reverse(text,text+len); ///反转一下求一次。
find_in_AC_automaton();
printf("%d\n",ans);
}
return 0;
}
题目意思,给出n个模式串和一个文本串,求n个模式串在文本串正串,和反向串中出现的个数。
AC自动机裸题,把文本串在AC自动机上跑一遍,统计一下有多少模式串出现在正着的文本串,
然后将文本串逆序,再在AC自动机上跑一边,统计一下有多少模式串出现在反着的文本串。
不能用动态链表写,开始的时候用动态链表写,TLE了。静态链表没试过,不知道能不能过。
不过动态链表TLE后,我直接用数组写,活生生对着链表的代码改成数组形式的,差点没看晕过去。
不过完美AC了。
AC代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
const int allSon = 26;
int node[500000][allSon]; ///字典树节点
int fail[500000]; ///fail指针
int num[500000]; ///以某个节点结尾的单词数
char patten[1010]; ///用来存放模式串
char text[5100010]; ///用来存放文本串
char str[5100010];
int ans; ///放答案
int id; ///给节点编号
///将模式串插入到字典树
void insertPatten()
{
int p = 0;
int index = 0;
while(patten[index]!='\0')
{
int uppercase = patten[index]-'A';
if(node[p][uppercase]==-1) ///对应的儿子不存在
{
memset(node[id],-1,sizeof(node[id]));
num[id] = 0;
fail[id] = -1; ///fail指针置-1代表空
node[p][uppercase] = id++; ///相应的位置放置节点编号
}
p = node[p][uppercase];
index++;
}
num[p]++;
}
///找失败指针,构造AC自动机
void build_AC_automaton()
{
queue<int>qu;
int p = 0; ///最开始指向根节点
qu.push(p);
while(!qu.empty())
{
p = qu.front(); ///出队节点编号
qu.pop();
for(int i = 0; i < allSon; i++)
{
if(node[p][i] != -1) ///看看这个孩子存不存在
{
if(p==0) ///p是根节点
{
fail[node[p][i]] = 0; ///节点的fail指针指向根
}
else
{
int temp = fail[p];
while(temp != -1)
{
if(node[temp][i] != -1)
{
fail[node[p][i]] = node[temp][i];
break;
}
temp = fail[temp];
}
if(temp == -1)
{
fail[node[p][i]] = 0;
}
}
qu.push(node[p][i]);
}
}
}
}
///在AC自动机中进行多模式匹配
void find_in_AC_automaton()
{
int p = 0; ///根节点
int index = 0;
while(text[index]!='\0')
{
int uppercase = text[index]-'A';
while(node[p][uppercase]==-1 && p!=0)
p = fail[p];
p = node[p][uppercase];
if(p == -1) p = 0;
int temp = p;
while(temp!=0 && num[temp]!=-1)
{
ans += num[temp];
num[temp] = -1;
temp = fail[temp];
}
index++;
}
}
///输入文本串
void inputText()
{
scanf("%s",str);//puts(str);
int res = 0;
int pos = 0;
bool flag = false;
int len = strlen(str);
for(int i = 0; i < len; i++)
{
if(str[i]>='A' && str[i]<='Z')
{
if(flag)
{
while(res--)
{
text[pos++] = str[i];
}
}
else text[pos++] = str[i];
}
if(str[i]=='[') flag = true;
if(str[i]>='0' && str[i]<='9') res = res*10+(str[i]-'0');
if(str[i]==']')
{
res = 0;
flag = false;
}
}
text[pos] = '\0';///puts(text);
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(node[0],-1,sizeof(node[0])); ///0号节点是空节点
num[0] = 0;
fail[0] = -1;
id = 1;
for(int i = 0; i < n; i++)
{
scanf("%s",patten);
insertPatten();
}
inputText();
build_AC_automaton();
ans = 0;
find_in_AC_automaton();
int len = strlen(text);
reverse(text,text+len); ///反转一下求一次。
find_in_AC_automaton();
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- hdu ----3695 Computer Virus on Planet Pandora (ac自动机)
- HDU 3695 Computer Virus on Planet Pandora(AC自动机)
- HDU 3695 Computer Virus on Planet Pandora (AC自动机)
- HDU 3695 Computer Virus on Planet Pandora (AC自动机)
- hdu 3695 Computer Virus on Planet Pandora AC自动机
- HDU 3695 Computer Virus on Planet Pandora(AC自动机)
- hdu 3695 Computer Virus on Planet Pandora AC自动机
- hdu 3695 Computer Virus on Planet Pandora(AC自动机)
- HDU 3695-Computer Virus on Planet Pandora(ac自动机)
- HDU - 3695 - Computer Virus on Planet Pandora(AC自动机)
- HDU 3695 Computer Virus on Planet Pandora(10年福州 AC自动机)
- HDU 3695 Computer Virus on Planet Pandora (AC自己主动机)
- AC自动机 - 多模式串的匹配 --- HDU 3695 Computer Virus on Planet Pandora
- hdu 3695 Computer Virus on Planet Pandora(AC自己主动机)
- AC自动机 - 多模式串的匹配 --- HDU 3695 Computer Virus on Planet Pandora(模板题)
- 【AC自动机】HDU 3695 Computer Virus on Planet Pandora 裸题
- HDU 3695 Computer Virus on Planet Pandora(自动机)
- 【AC自动机】HDU 3695 Computer Virus on Planet Pandora 裸题
- HDOJ 3695 Computer Virus on Planet Pandora (AC自动机)
- hdu 3695:Computer Virus on Planet Pandora(AC自动机,入门题)