您的位置:首页 > 其它

【AC自动机】HDU 3695 Computer Virus on Planet Pandora 裸题

2014-09-05 20:42 357 查看
n个单词在一个字符串和该串的逆串出现了几个

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define cler(arr, val)    memset(arr, val, sizeof(arr))
#define IN     freopen ("in.txt" , "r" , stdin);
#define OUT  freopen ("out.txt" , "w" , stdout);
typedef long long  LL;
const int MAXN = 1000006;//点数的最大值
const int MAXM = 20006;//边数的最大值
const int INF = 11521204;
const int mod=1000000007;
#define maxnode 250001
#define sigma_size 26
int ans;
struct Trie
{
int ch[maxnode][sigma_size];
int val[maxnode];    //该单词在模式串中出现的次数
int last[maxnode];
int f[maxnode];      //失配数组
int num[maxnode];    //该单词出现在文本串的次数
int pre[maxnode];    //该单词的前驱
int len[maxnode];    //以该单词结尾的单词长度
int Char[maxnode];   //该单词对应的字母
int sz;
void init()
{
sz=1;
memset(ch,0,sizeof(ch));
memset(val, 0, sizeof(val));
memset(f,0,sizeof(f));
memset(last,0,sizeof(last));    //记录该节点前一个节点是谁
memset(len, 0, sizeof(len));
}
int idx(char c)
{
return c-'A';
}
int insert(char *s)
{
int u = 0;
for(int i = 0; s[i] ; i++)
{
int c = idx(s[i]);
if(!ch[u][c])
ch[u][c] = sz++;
u = ch[u][c];
}
val[u] ++;
return u;
}
void getFail()
{
queue<int> q;
for(int i = 0; i<sigma_size; i++)
if(ch[0][i]) q.push(ch[0][i]);

while(!q.empty())
{
int r = q.front();
q.pop();
for(int c = 0; c<sigma_size; c++)
{
int u = ch[r][c];
if(!u)continue;
q.push(u);
int v = f[r];
while(v && ch[v][c] == 0)
v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环
f[u] = ch[v][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
}
void find(char *T)
{
int u = 0;
for(int i = 0; T[i] ; i++)
{
int c = idx(T[i]);
while(u && ch[u][c]==0)
u = f[u];
u = ch[u][c];
int temp = u;
while(temp && val[temp])  //沿失配边走 || 若沿失配边走时一定要节点为单词结尾则改成while(temp && val[temp])
{
ans+=val[temp];
val[temp]=0;
temp = f[temp];
}
}
return ;
}
} ac;
char s[5110000],s1[5110000];
int main()
{
int t,n;
// IN;
scanf("%d",&t);
while(t--)
{
ac.init();
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%s",s);
ac.insert(s);
}
ac.getFail();
int i=0;
char c;
getchar();
while(c=getchar(),c>10)
{
if(c=='[')
{
int x;
scanf("%d%c]",&x,&c);
while(x--) s[i++]=c;
}
else
{
s[i++]=c;
}
}
s[i]=s1[i]=0;
for(int j=0;j<i;j++)
s1[i-j-1]=s[j];
ans=0;
ac.find(s);ac.find(s1);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: