ZOJ 3228 AC自动机

来源:互联网 发布:知乎赞同和感谢 编辑:程序博客网 时间:2024/05/17 01:16

题意

给一些字符串,后面跟一个数字。如果0的话,就允许统计层叠的的字符串个数。如果1的话,就只能统计不层叠的字符串个数。要求输出统计个数

题解

实现起来最简单的方式,也是大家用的最多的方式就是用一个AC自动机,然后在统计的时候,开两个数组分别统计允许层叠的个数和不允许层叠的个数。最后需要输出哪种类型的个数,就直接输出就可以了。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#include<stack>#include<string>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define MEM(a,b) memset(a,b,sizeof(a))#define INF 0x3f3f3f3f#define LL long long#define MAXN 100010#define MOD 1000000007#define EPS 1e-10using namespace std;char tar[100010];int mp[100010],tp[100010];int val[600010],f[600010],last[600010],cnt[600010][2],pos[600010];char st[15];int ch[600010][26];int sz;void insert(int i) {    int len=strlen(st);    int u=0;    UP(i,0,len) {        int x=st[i]-'a';        if(!ch[u][x]) {            ch[u][x]=sz++;        }        u=ch[u][x];    }    val[u]=len;    mp[i]=u;//    cout<<val[u]<<" "<<u<<endl;}void getFail() {    MEM(f,0);    MEM(last,0);    queue<int> q;    UP(i,0,26) {        int x=ch[0][i];        if(x) {            q.push(x);        }    }    W(!q.empty()) {        int r=q.front();        q.pop();        UP(i,0,26) {            int x=ch[r][i];            if(!x) {                ch[r][i]=ch[f[r]][i];                continue;            }            q.push(x);            int v=f[r];            f[x]=ch[v][i];            last[x]=val[f[x]]>0?f[x]:last[f[x]];        }    }}void solve(int u,int p) {    if(u!=0) {        cnt[u][0]++;        if(pos[u]==-1||(pos[u]+val[u])<=p) {            cnt[u][1]++;            pos[u]=p;        }        solve(last[u],p);    }}void find() {    int len=strlen(tar);    int u=0;    UP(i,0,len) {        int x=tar[i]-'a';        u=ch[u][x];        if(val[u])            solve(u,i);        else if(last[u])            solve(last[u],i);    }}int main() {    int ks=1;    W(~scanf("%s",tar)) {        MEM(ch,0);        MEM(val,0);        MEM(cnt,0);        MEM(pos,-1);        MEM(mp,0);        MEM(tp,0);        sz=1;        int n;        scanf("%d",&n);        UP(i,0,n) {            scanf("%d%s",&tp[i],st);            insert(i);        }        getFail();        find();        printf("Case %d\n",ks++);        UP(i,0,n) {            printf("%d\n",cnt[mp[i]][tp[i]]);        }        puts("");    }}