本文主要是介绍zoj-3228 Searching the String AC自动机,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
用一个val数组记录每一个单词结尾对应的位置,pos数组记录某个节点的深度(其实就是记录单词的长度的),然后用一个op数组记录一下每一个单词对应的询问方式,主要是查询分为了可重叠和不可重叠,不可重叠的话就是用一个last数组来记录查询过程中上次到达该单词的位置last[now]=i,如果再经过now点满足i-last[now]>=pos[now]就满足不重叠。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define me(a,b) memset(a,b,sizeof(a))
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
#define max4(a,b,c,d) max(max(a,b),max(c,d))
#define max3(x,y,z) max(max(x,y),max(y,z))
typedef long long ll;
using namespace std;
const int maxn=6e5+5;
const int maxm=1e5+5;
const int N=26;
int ans[maxn][2];//记录答案
int op[maxn];
int val[maxn];//记录节点末尾位置
struct AC
{int fail[maxn];int last[maxn];int pos[maxn];//记录单词对应的长度int ch[maxn][30];int cnt,root;int newnode(){for(int i=0;i<N;i++)ch[cnt][i]=0;pos[cnt]=fail[cnt++]=0;return cnt-1;}void init(){cnt=0;root=newnode();}void insert(char *s,int x){int len=strlen(s);int u=0;for(int i=0;i<len;i++){int v=s[i]-'a';if(!ch[u][v])ch[u][v]=newnode();u=ch[u][v];pos[u]=i+1;}val[x]=u;}void getfail(){queue<int >q;int u=0;for(int i=0;i<N;i++)if(ch[u][i])q.push(ch[u][i]);while(!q.empty()){u=q.front();q.pop();for(int i=0;i<N;i++){if(ch[u][i]){fail[ch[u][i]]=ch[fail[u]][i];q.push(ch[u][i]);}elsech[u][i]=ch[fail[u]][i];}}}void getans(char *s){memset(last,-1,sizeof(last));memset(ans,0,sizeof(ans));int len=strlen(s);int u=0;for(int i=0;i<len;i++){u=ch[u][s[i]-'a'];for(int j=u;j;j=fail[j]){ans[j][0]++;if(i-last[j]>=pos[j])//看看当前位置与之前到达该点的位置差是否大于单词长度{ans[j][1]++;last[j]=i;}}}}
}AC;
char str[maxm];
char ss[10];
int main()
{int n,cas=0;while(scanf("%s",str)!=EOF){AC.init();scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d%s",&op[i],ss);AC.insert(ss,i);}AC.getfail();AC.getans(str);printf("Case %d\n",++cas);for(int i=0;i<n;i++)printf("%d\n",ans[val[i]][op[i]]);printf("\n");}
}
这篇关于zoj-3228 Searching the String AC自动机的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!