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.
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
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
题意:给出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;
}