HDU 6208 The Dominator of Strings

来源:互联网 发布:广东粤数大数据 电话 编辑:程序博客网 时间:2024/06/06 14:41

The Dominator of Strings

Problem Description
Here you have a set of strings. A dominator is a string of the set dominating all strings else. The string S is dominated by T if S is a substring of T.
 

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 N indicating the size of the set.
Each of the following N lines describes a string of the set in lowercase.
The total length of strings in each case has the limit of 100000.
The limit is 30MB for the input file.
 

Output
For each test case, output a dominator if exist, or No if not.
 

Sample Input
310youbetterworsericherpoorersicknesshealthdeathfaithfulnessyoubemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness5abccdeabcdeabcdebcde3aaaaaaaaabaaaac
 

Sample Output
youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulnessabcdeNo
 

 
题意:给出n个串,判断其中的n-1个串是否是另一个串str的子串,如果不是,输出“No",否则输出str。
分析:其中str必须是最长的,那么先找出所有串中最长的串,然后用n-1个串构造AC自动机,匹配str就可以了。也有KMP的做法,每次询问str之外的串,每次都对这些串构造next数组,然后再和str匹配。AC自动机做法的时间是KMP的两倍,可能常数较大吧。另外对于输入的话,不能用cin,比赛的时候用AC自动机TLE了一发,然后队友用指针优化了一下,就过了。。
代码:

AC自动机:
#include<bits/stdc++.h>using namespace std;int vis[505];int N;struct AC_auto{    const static int LetterSize=26;    const static int TrieSize=100005;    int cnt,root;    int next_[TrieSize][LetterSize],end_[TrieSize],fail[TrieSize];    int newnode(){        memset(next_[cnt],-1,sizeof(next_[cnt]));        end_[cnt]=0;        return cnt++;    }    void init(){        cnt=0;        root=newnode();    }    int get_index(char x){        return x-'a';    }    void Insert(char* s){        int len=strlen(s);        int p=root;        for(int i=0;i<len;i++){            int index=get_index(s[i]);            if(next_[p][index]==-1){                next_[p][index]=newnode();            }            p=next_[p][index];        }        end_[p]++;//printf("end=%d\n",end_[p]);    }    void build(){        fail[root]=0;        queue<int> q;        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()==0){            int p=q.front();            q.pop();            for(int i=0;i<LetterSize;i++){                if(next_[p][i]==-1){                    next_[p][i]=next_[fail[p]][i];                }                else{                    fail[next_[p][i]]=next_[fail[p]][i];                    q.push(next_[p][i]);                }            }        }    }    int match(char *s){        int ans=0;        int p=root;        int len=strlen(s);        for(int i=0;i<len;i++){            int index=get_index(s[i]);            p=next_[p][index];            int cur=p;            while(cur!=root){                if(end_[cur]){                    ans+=end_[cur];                    end_[cur]=0;                }                cur = fail[cur];            }        }        return ans;    }};AC_auto ac;char *str[200005];char *s;char temp[200005];int main(){    int N;    scanf("%d",&N);    while(N--){        int n;        scanf("%d",&n);        int len=0,pos;        int flag=1;        int num=0;        s=temp;        for(int i=1;i<=n;i++){            scanf("%s",s);            str[i]=s;            if(strlen(s)>len){                len=strlen(s);                pos=i;            }            s+=strlen(s)+1;        }        for(int i=1;i<=n;i++){            if(strlen(str[i])==len){                if(strcmp(str[i],str[pos])!=0){                    flag=0;                    break;                }            }        }        if(flag==0){            printf("No\n");        }        else{//printf("num=%d\n",num);            ac.init();            for(int i=1;i<=n;i++){                if(strlen(str[i])!=len){//printf("pos=%d\n",i);                    num++;//cout<<str[i]<<endl;                    ac.Insert(str[i]);                }            }            ac.build();//cout<<str[pos]<<endl;            int ans=ac.match(str[pos]);            //printf("ans=%d\n",ans);            if(ans!=num){                printf("No\n");            }            else{                printf("%s\n",str[pos]);            }        }    }    return 0;}

KMP:
#include<bits/stdc++.h>using namespace std;int next_[200005];char *str[200005];char *s;char temp[200005];void get_next(char *tmp){    int i=0;    int j=-1;    next_[0]=-1;    int len2=strlen(tmp);    while(i<len2){        if(j==-1||tmp[i]==tmp[j]){            i++;            j++;            next_[i]=j;        }        else{            j=next_[j];        }    }}int KMP(char *tmp,char *s){    int i=0;    int j=0;    get_next(tmp);    int len1=strlen(s);    int len2=strlen(tmp);    while(i<len1){        if(j==-1||s[i]==tmp[j]){            i++;            j++;        }        else{            j=next_[j];        }        if(j==len2){            return true;        }    }    return -1;}int main(){    int N;    scanf("%d",&N);    while(N--){        int n;        scanf("%d",&n);        int pos;        int len=0;        s=temp;        for(int i=1;i<=n;i++){            scanf("%s",s);            str[i]=s;            if(strlen(s)>len){                len=strlen(s);                pos=i;            }            s+=strlen(s)+1;        }        int flag=1;        for(int i=1;i<=n;i++){            if(strlen(str[i])==len){                if(strcmp(str[i],str[pos])!=0){                    flag=0;                    break;                }            }        }        if(flag==0){            printf("No\n");        }        else{            int ans=0;            int num=0;            for(int i=1;i<=n;i++){                if(strlen(str[i])!=len){                    num++;                    if(KMP(str[i],str[pos])!=-1){                        ans++;                    }                    else{                        break;                    }                }            }//printf("%d %d\n",ans,num);            if(num==ans){                printf("%s\n",str[pos]);            }            else{                printf("No\n");            }        }    }    return 0;}


原创粉丝点击