题目:
1 5 6 orz sto kirigiri danganronpa ooooo o kyouko dangan ronpa ooooo ooooo
1 1 0 3 7
题意:字符串匹配,多个模式串匹配源串。
思路:AC自动机模板题。
代码:
//AC 自动机
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
inline int Max(int a,int b)
{
return a>b?a:b;
}
inline int Min(int a,int b)
{
return a>b?b:a;
}
#define maxnode 600010
#define sigma_size 26
struct Trie
{
int ch[maxnode][sigma_size];//下一指针
int val[maxnode];//匹配进度
int haha[maxnode];//节点i的成功匹配数
int f[maxnode];//失配指针
int sz;//size
//初始化
void init()
{
sz=1;
memset(ch,0,sizeof(ch));
memset(val, 0, sizeof(val));
memset(f,0,sizeof(f));
memset(haha,0,sizeof(haha));
}
//字符 c 的 index
int idx(char c)
{
return c-'a';
}
//插入串 s
int insert(char *s)
{
//
int u = 0, len = strlen(s);
for(int i = 0; i < len; i++)
{
//获取index
int c = idx(s[i]);
if(!ch[u][c]) ch[u][c] = sz++;//无路则建立指针到最后一个节点
u = ch[u][c];//到下一节点
}
val[u] ++; //将串结束的位置的val++
return u; //返回串S 结束位置的指针
}
//计算失败指针
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();
//取队首为r
//遍历r的所有下级
for(int c = 0; c<sigma_size; c++)
{
int u = ch[r][c];
if(!u)continue;//如果下一节点是根节点,跳过
//将r的下级加入队列
q.push(u);
int v = f[r];
///沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环
while(v && ch[v][c] == 0) v = f[v];
f[u] = ch[v][c];//改变失配指针
}
}
}
//匹配 串T
void find(char *T)
{
int len = strlen(T), j = 0;//j为当前节点编号(0代表根节点)
for(int i = 0; i < len; i++)
{
int c = idx(T[i]);
while(j && ch[j][c]==0) //当j不是根节点且j到c无路(失配)
j = f[j];//走失配指针到下一节点(回滚)
//循环结束时:
//j 为根节点 或 j到c有路(可配)
j = ch[j][c];//j到下一节点,若j为根节点且没有路,则j还会走到根节点
int temp = j;
//标记整个路上的
while(temp)//当temp不是根
{
haha[temp]++;//在temp节点的进度+1
temp = f[temp];//回退到失败后节点
}
}
}
};
Trie ac;
char P[100011][10010];
int ans[100010];
char S1[100010];
int main()
{
int t,m,n;
scanf("%d",&t);
while(t--)
{
ac.init();
scanf("%d%d",&m,&n);
for(int i = 1; i <= m; i++)
{
scanf("%s",P[i]);
}
for(int i = 1; i <= n; i++)
{
scanf("%s",S1);
ans[i] = ac.insert(S1);
}
ac.getFail();
for(int i = 1; i <= m; i++)
{
memset(ac.haha,0,sizeof(ac.haha));
ac.find(P[i]);
int sum = 0;
for(int i=1; i <= n; i++)
sum += ac.haha[ans[i]];
printf("%d\n",sum);
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u013840081/article/details/48070739