hdu 6208 (ac自动机)

来源:互联网 发布:java源码如何变成软件 编辑:程序博客网 时间:2024/05/24 06:16

Here you have a set of strings. A dominator is a string of the set dominating all strings else. The string SS is dominated by TT if SS is a substring of TT.
Input
The input contains several test cases and the first line provides the total number of cases.
For each test case, the first line contains an integer NN indicating the size of the set.
Each of the following NN lines describes a string of the set in lowercase.
The total length of strings in each case has the limit of 100000100000.
The limit is 30MB for the input file.
Output
For each test case, output a dominator if exist, or No if not.
Sample Input
3
10
you
better
worse
richer
poorer
sickness
health
death
faithfulness
youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness
5
abc
cde
abcde
abcde
bcde
3
aaaaa
aaaab
aaaac
Sample Output
youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness
abcde
No

题意:问有没有一个串包含其他所有串
找最长的串匹配就好

我的板子得加优化,优化就是 用strcmp判和最长的相等的

#include<iostream>  #include<cstdio>  #include<cstring>  #include<queue>  #include<algorithm>  using namespace std;  const int LetterSize = 26;  const int TrieSize = 10000*50+5;  int tot, root, fail[TrieSize], val[TrieSize], Next[TrieSize][LetterSize];  int mark[TrieSize];int newnode(void)  {      memset(Next[tot], -1, sizeof(Next[tot]));      val[tot] = 0;      mark[tot] = 0;    return tot++;  }  void init(void)  {      tot = 0;      root = newnode();  }  int getidx(char x)  {      return x-'a';  }  void insert(char *ss)  {      int len = strlen(ss);      int now = root;      for(int i = 0; i < len; i++)      {          int idx = getidx(ss[i]);          if(Next[now][idx] == -1)              Next[now][idx] = newnode();          now = Next[now][idx];      }      val[now]++;  }  void build()  {      queue<int> Q;      fail[root] = root;      for(int i = 0; i < LetterSize; i++)      {          if(Next[root][i] == -1)              Next[root][i] = root;          else              fail[Next[root][i]] = root, Q.push(Next[root][i]);      }      while(!Q.empty())      {          int now = Q.front(); Q.pop();          for(int i = 0; i < LetterSize; i++)          {              if(Next[now][i] == -1)                  Next[now][i] = Next[fail[now]][i];              else                  fail[Next[now][i]] = Next[fail[now]][i], Q.push(Next[now][i]);          }      }  }  int match(char *ss)  {      int len = strlen(ss), now = root, res = 0;      for(int i = 0; i < len; i++)      {          int idx = getidx(ss[i]);          int tmp = now = Next[now][idx];          while(tmp&&!mark[tmp])          {              res += val[tmp];              val[tmp] = 0;              mark[tmp]=1;            tmp = fail[tmp];          }      }      return res;  }  const int maxn = 1e6+5;  char s[maxn+maxn+100];  int st[maxn];int le[maxn];int main()  {      int t, n;      scanf("%d",&t);     while(t--)      {          scanf("%d", &n);        int l=0;          int lenn=0,MAX=0,flag=0;        for(int i = 1; i <= n; i++)          {            scanf(" %s", s+l);              int len=strlen(s+l);            le[i]=len;            st[i]=l;            if(len>lenn)            {                lenn=len;                MAX=i;            }            l=l+len+1;        }        int ab=0;        init();        for(int i=1;i<=n;i++)        {            if(le[i]==lenn)            {                if(strcmp(s+st[i],s+st[MAX])!=0)                {                    flag=1;                    break;                }            }            else insert(s+st[i]),ab++;        }        if(flag)         {            printf("No\n");            continue;        }        build();        int tt=match(s+st[MAX]);        if(tt==ab) printf("%s\n",s+st[MAX] );           else printf("No\n");    }      return 0;  }

另外 比较好的板子是能直接过的,这个相比于上面的优化在于last数组,保证转移到的位置尽可能是有值的位置,小优化

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=100010;const int maxm=100010;const int SIGMA_SIZE=26;int n;char t[maxn],s[2*maxn+100];int st[maxn];struct AC{    int ch[maxm][26];    int val[maxm];    int fail[maxm],last[maxm];    int sz;    void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;}    int idx(char x){return x-'a';}    void insert(char *s)    {        int u=0;        int n=strlen(s);        for(int i=0;i<n;i++)        {            int c=idx(s[i]);            if(!ch[u][c])            {                memset(ch[sz],0,sizeof(ch[sz]));                val[sz]=0;                ch[u][c]=sz++;            }            u=ch[u][c];        }        val[u]++;    }    void getfail()    {        queue<int> q;        fail[0]=0;        int u=0;        for(int i=0;i<SIGMA_SIZE;i++)        {            u=ch[0][i];            if(u){q.push(u);fail[u]=0;last[u]=0;}        }        while(!q.empty())        {            int r=q.front();q.pop();            for(int i=0;i<SIGMA_SIZE;i++)            {                u=ch[r][i];                if(!u){ch[r][i]=ch[fail[r]][i];continue;}                q.push(u);                int v=fail[r];                while(v&&!ch[v][i])v=fail[v];                fail[u]=ch[v][i];                last[u]=val[fail[u]]?fail[u]:last[fail[u]];            }        }    }    int find(char *s)    {        int u=0,cnt=0;        for(int i=0;s[i];i++)        {            int c=idx(s[i]);            u=ch[u][c];            int temp=0;//必须赋初值为0,表示如果下面两个判断都不成立的时候while可以正常执行            if(val[u])                temp=u;            else if(last[u])                temp=last[u];            while(temp)            {                cnt+=val[temp];                val[temp]=0;                temp=last[temp];            }        }        return cnt;    }}tree;int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        int maxlen=0;        tree.clear();        int lenn=0,l=0;        int MAX=0;        for(int i=1;i<=n;i++)        {            scanf("%s",s+l);            int len=strlen(s+l);            st[i]=l;            if(len>lenn)            {                lenn=len;                MAX=i;            }            l=l+len+1;        }        for(int i=1;i<=n;i++)        {            if(i==MAX) continue;            tree.insert(s+st[i]);        }        tree.getfail();        int ans=tree.find(s+st[MAX]);        if(ans==n-1)        {            printf("%s\n",s+st[MAX]);        }        else        {            printf("No\n");        }    }    return 0;}

标程是假算法 strstr

#include <bits/stdc++.h>using namespace std;char s[200010];int st[100010];int main(){    int T;    scanf("%d",&T);    while(T--)    {        int l=0,lenn=0,MAX=0;        int n;        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%s",s+l);            st[i]=l;            int len=strlen(s+l);            if(len>lenn)            {                lenn=len;                MAX=i;            }            l=l+len+1;        }        int flag=0;        for(int i=1;i<=n;i++)        {            if(i==MAX) continue;            if(strstr(s+st[MAX],s+st[i])==NULL)            {                flag=1;                break;            }        }        if(flag) printf("No\n");        else printf("%s\n",s+st[MAX] );    }}
原创粉丝点击