ZOJ Searching the String(match指针暴力跳fail)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ Searching the String(match指针暴力跳fail)相关的知识,希望对你有一定的参考价值。
给出一个文本串 s s s和 n n n个模式串
问每个模式串 f i f_i fi在文本串 s s s中最多出现几次
t y p e = = 0 type==0 type==0表示可覆盖, t y p e = = 1 type==1 type==1表示不可覆盖
比如 a b a aba aba在 a b a b a ababa ababa中,若可覆盖则出现 2 2 2次,否则只出现一次
t y p e = = 0 type==0 type==0的模式串只需要跑一遍 a c ac ac自动机即可
t y p e = = 1 type==1 type==1的模式串,考虑第一次匹配到的时候可以直接让答案加一
第二次匹配到的时候如果和上次没有重叠答案也加一,这个只需要记录以下最后一次匹配位置即可
如果和上次有重合,直接丢弃这次的匹配结果即可,答案不加一.
设 a [ 1... l ] a[1...l] a[1...l]匹配到自动机位置 k k k,直接从 k k k往上暴力跳 f a i l fail fail即可
因为每个文本串的长度小于等于 6 6 6,所以只需要跳 6 6 6次 m a t c h match match指针(只指向有单词节点)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
char a[maxn],b[maxn];
int n,m,casenum;
typedef pair<int,int>p;
vector<p>vec[maxn];
int zi[maxn][30],id,len[maxn],type[maxn],ID[maxn],ok[maxn];
void insert(char s[],int is)
{
int now = 0, le = strlen( s+1 );
for(int i=1;i<=le;i++)
{
if( zi[now][s[i]-'a']==0 ) zi[now][s[i]-'a'] = ++id;
now = zi[now][s[i]-'a'];
}
len[now] = le; ok[now] = 1; ID[is] = now;
}
int fail[maxn],ans[maxn][2],pre[maxn],match[maxn];
void make_fail()
{
queue<int>q;
for(int i=0;i<=25;i++) if( zi[0][i] ) q.push( zi[0][i] );
while( !q.empty() )
{
int u = q.front(); q.pop();
for(int i=0;i<=25;i++)
{
int v = zi[u][i];
if( v )
{
fail[v] = zi[fail[u]][i],q.push( v );
int temp = zi[fail[u]][i];
if( ok[temp] ) match[v] = temp;
else match[v] = match[temp];
}
else
zi[u][i] = zi[fail[u]][i];
}
}
}
void init()
{
for(int i=0;i<=id;i++)
{
memset( zi[i],0,sizeof zi[i] );
fail[i] = match[i] = ok[i] = len[i] = 0;
pre[i] = ans[i][0] = ans[i][1] = 0;
vec[i].clear();
}
id = 0;
for(int i=0;i<=n;i++) ID[i] = 0;
}
int main()
{
while( scanf("%s%d",a+1,&n)!=EOF )
{
for(int i=1;i<=n;i++)
{
scanf("%d%s",&type[i],b+1 );
insert( b,i );
}
make_fail();
int now = 0;
m = strlen( a+1 );
for(int i=1;i<=m;i++)
{
now = zi[now][a[i]-'a'];
int f = now;
while( f!=0 )
{
ans[f][0]++;
if( pre[f]+len[f]<=i ) ans[f][1]++, pre[f] = i;
f = match[f];
}
}
printf("Case %d\\n",++casenum);
for(int i=1;i<=n;i++) printf("%d\\n",ans[ID[i]][type[i]] );
init();
puts("");
}
return 0;
}
以上是关于ZOJ Searching the String(match指针暴力跳fail)的主要内容,如果未能解决你的问题,请参考以下文章
ZOJ3228 Searching the String(AC自动机)
ZOJ 3228 Searching the String (AC自己主动机)
ZOJ Searching the String(match指针暴力跳fail)