The Dominator of Strings HDU - 6208(ac自动机板题)

题意:

  就是求是否有一个串 是其它所有串的母串

解析:

  把所有的串都加入到trie数中  然后用最长的串去匹配就好了

emm。。开始理解错题意了。。。看成了只要存在一个串是另一个的母串就好。。

然后输出这样的串。。。用后缀数组写完后。。。才发现  理解错了 emm。。

指针的会超时emm。。。然后才学了 用数组写

#include<stdio.h>
#include<string.h>
#include<queue>
#include<string>
#include<iostream>
#define maxn 1000010
using namespace std;
int n;
    int nxt[maxn][30],fail[maxn],edd[maxn],root,L;//nxt记录节点,在这里edd指针代表以当前节点为字符串尾的字符串个数
    int vis[maxn];
    int newnode()
    {
        for(int i=0;i<26;i++)
            nxt[L][i]=-1;//节点连接的边初始化为-1
        edd[L]=0;
        vis[L]=0;
        return L++;
    }
    void init()
    {
        L=0;
        root=newnode();
    }

    void insert(char *str)//trie树的建立
    {
        int l = strlen(str);
        int now=root;
        for(int i=0;i<l;i++)
        {
            int x = str[i] - 'a';
            if(nxt[now][x]==-1)nxt[now][x]=newnode();
            now=nxt[now][x];
        }
        edd[now]++;
    }
    void build()//建立ac自动机
    {
        queue<int> Q;
        for(int i=0;i<26;i++)
        {
            if(nxt[root][i]==-1)nxt[root][i]=root;
            else                                 //若有连边则将节点加入队列 ,并将fail指针指向root
            {
                fail[nxt[root][i]]=root;
                Q.push(nxt[root][i]);
            }
        }
        while(!Q.empty())
        {
            int now=Q.front();
            Q.pop();
            for(int i=0;i<26;i++)
            {
                if(nxt[now][i]==-1)            //若无连边,则将该边指向当前节点fail指针指向的相应字符连接的节点
                    nxt[now][i]=nxt[fail[now]][i];
                else                            //若有连边,则将儿子节点的fail指针指向当前节点fail指针指向相应字符接的节点
                {
                    fail[nxt[now][i]]=nxt[fail[now]][i];
                    Q.push(nxt[now][i]); //加入队列继续遍历
                }
            }
        }
    }
    int query(char str[])
    {
        int l = strlen(str);
        int now=root;
        int res=0;
        for(int i=0;i<l;i++)
        {
            int x = str[i] - 'a';
            now=nxt[now][x];
            int temp=now;
            while(temp!=root&&vis[temp]==0)//根据题目要求改变形式
            {
                res+=edd[temp];
                edd[temp]=0;
                vis[temp]=1;
                temp=fail[temp];
            }
        }
        return res; //在这里返回的是匹配到的模式串的数量
    }
char str[maxn], ans[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        init();
        int ma=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",str);
            int l=strlen(str);
            if(ma<l)
            {
                ma=l;
                strcpy(ans,str);
            }
            insert(str);
        }
        build();
        int sum=query(ans);
        if(sum==n) puts(ans);
        else puts("No");
    }
}

猜你喜欢

转载自www.cnblogs.com/WTSRUVF/p/9507369.html
今日推荐