csu 1951: 图样 AC自动机

来源:互联网 发布:筛选的数据求和 编辑:程序博客网 时间:2024/04/29 21:34

题目链接点这里


我们把两种字符串都插入到自动机中,用End[u] = mask来状压记录下以u节点结尾的喜欢字符串有哪些(比如这个点结尾有第i个字符串和第j个字符串,,那么End[u]=(1<<i)+(1<<j) )。

之后那我们把讨厌字符串的End[u]记为-1.。

构造出自动机之后,套路状态转移建图。然后bfs就好了 ,什么?你不会ac自动机上的状态转移?请做这题 

#include<iostream>#include<cstdio>#include<math.h>#include<algorithm>#include<map>#include<set>#include<bitset>#include<unordered_map>#include<stack>#include<queue>#include<string.h>#include<cstring>#include<vector>#include<time.h>#include<stdlib.h>using namespace std;#define INF 0x3f3f3f3f#define INFLL 0x3f3f3f3f3f3f3f3f#define FIN freopen("input.txt","r",stdin)#define mem(x,y) memset(x,y,sizeof(x))typedef unsigned long long ULL;typedef long long LL;#define fuck(x) cout<<"q"<<endl;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef pair<pair<int,int>,int> PIII;typedef pair<int,int> PII;const double eps=1e-8;const int MX=555;const int P=1e9+7;int n,m;char s[1000+10];struct AC_trie{    int root,cnt;    int End[5000+10],to[5000+10][10],fail[5000+10];//改    int newnode()    {        for(int i=0; i<10; i++) to[cnt][i]=0;//改        End[cnt]=0;        return cnt++;    }    void init()    {        cnt=1;        root=newnode();    }    void insert(char *s,int w)//0无,0到n-1是喜欢,-1是讨厌    {        int now=root;        for(char *ss=s; *ss; ss++)        {            int v=*ss-'a';//改            if(!to[now][v])to[now][v]=newnode();            now=to[now][v];        }        if(w!=-1)            End[now]|=(1<<w);//改        else End[now]=-1;//改    }    void build()    {        queue<int> my;        fail[root]=root;        for(int i = 0; i < 10; i++)//改            if(!to[root][i])                to[root][i]= root;            else            {                fail[to[root][i]]=root;                my.push(to[root][i]);            }        while(!my.empty())        {            int u=my.front();            my.pop();            for(int i=0; i<10; i++)   //改            {                int v=to[u][i];                if(v)                {                    fail[v]=to[fail[u]][i];                    my.push(v);                }                else to[u][i]=to[fail[u]][i];                if(End[u]==-1)continue;                if(End[fail[u]]==-1)End[u]=-1;                else End[u]|=End[fail[u]];            }        }    }    int head[MX],edge_cnt;    struct Edge    {        int nxt,to;        char c;    } E[MX*MX];    void edge_init()    {        mem(head,-1);        edge_cnt=0;    }    void edge_add(int u,int v,char c)    {        E[edge_cnt].nxt=head[u];        E[edge_cnt].to=v;        E[edge_cnt].c=c;        head[u]=edge_cnt++;    }    void build_edge()    {        edge_init();        for(int i=1; i<cnt; i++)        {            for(int j=0; j<10; j++) if(End[to[i][j]]!=-1&&i!=to[i][j])                {                    edge_add(i,to[i][j],'a'+j);                }        }    }    int d[MX][1<<15];    int pre[MX][1<<15][3];    int bfs()    {        for(int i=1; i<cnt; i++)            for(int j=0; j<(1<<n); j++)d[i][j]=0;        int t=(1<<n)-1;        queue<PII> Q;        Q.push(PII(1,0));        d[1][0]=0;        while(!Q.empty())        {            int u=Q.front().first,s=Q.front().second;            Q.pop();            for(int  i=head[u]; ~i; i=E[i].nxt)            {                int v=E[i].to;                int ss=s;                if(End[v]!=-2)ss|=End[v];                if(d[v][ss]==0)                {                    pre[v][ss][0]=u;                    pre[v][ss][1]=s;                    pre[v][ss][2]=E[i].c-'a';                    d[v][ss]=d[u][s]+1;                    Q.push(PII(v,ss));                }                if(ss==t)return v;            }        }        return -1;    }    char ss[11111];    char* print(int s)    {        int cnt=0;        int now=s,w=(1<<n)-1;        while(now!=1||w!=0)        {            int tnow=now,tw=w;            ss[cnt++]=pre[tnow][tw][2]+'a';            now=pre[tnow][tw][0];            w=pre[tnow][tw][1];        }        ss[cnt]=0;        reverse(ss,ss+cnt);        return ss;    }} AC;int main(){    FIN;    while(cin>>n>>m)    {        AC.init();        for(int i=0; i<n; i++)        {            scanf("%s",s);            AC.insert(s,i);        }        for(int i=0; i<m; i++)        {            scanf("%s",s);            AC.insert(s,-1);        }        AC.build();        AC.build_edge();        int ans=AC.bfs();        if(ans!=-1)        {            puts(AC.print(ans));        }        else puts("-");    }    return 0;}


原创粉丝点击