The Dominator of Strings
Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 2044 Accepted Submission(s): 738
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
——————————————————————————————————
题目的意思是给出若干个串,判断是否能找出一个串,所有串都是它的字串
思路:AC自动机,首先这个串一定是最长的,所以我们记录下当前最长串,如果处理的串比最长串长那么把之前的最长串扔到字典树里,更新最长串;如果一样长先标记下,如果之后于到更长的的标记清空,最后判标记是否还在,记录重复;否则就把当前串扔到字典树里,最后跑一边AC自动机
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
struct Trie
{
int next[maxn][26],fail[maxn],end[maxn];
int root,L;
int newnode()
{
memset(next[L],-1,sizeof next[L]);
end[L++] = 0;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = 0; i < len; i++)
{
if(next[now][buf[i]-'a'] == -1)
next[now][buf[i]-'a'] = newnode();
now = next[now][buf[i]-'a'];
}
end[now]++;
}
bool findintree(char buf[])
{
int len =strlen(buf);
int now=root;
int flag=0;
for(int i=0; i<len; i++)
{
if(next[now][buf[i]-'a']!=-1)
{
flag=1;
break;
}
now=next[now][buf[i]-'a'];
}
return end[now]&&!flag;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0; i < 26; 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 < 26; 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 query(char buf[])
{
int len = strlen(buf);
int now = root;
int res = 0;
for(int i = 0; i < len; i++)
{
now = next[now][buf[i]-'a'];
int temp = now;
while( temp != root )
{
res += end[temp];
end[temp] = 0;
temp = fail[temp];
}
}
return res;
}
void debug()
{
printf("id = ,fail = ,end = ,chi = [ a b c d e f g h i j k l m n o p q r s t u v w x y z]\n");
for(int i = 0; i < L; i++)
{
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
for(int j = 0; j < 26; j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
}ac;
char dic[100005],str[100005];
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
int flag=0;
str[0]='\0';
ac.init();
scanf("%d",&n);
int kk=1;
for(int i=0;i<n;i++)
{
scanf("%s",dic);
if(strlen(dic)>strlen(str))
{
flag=0;
if(str[0]!='\0')
ac.insert(str);
strcpy(str,dic);
}
else if(strlen(dic)==strlen(str))
{
if(strcmp(dic,str)!=0)
{
flag=1;
ac.insert(dic);
}
else
kk++;
}
else
ac.insert(dic);
}
ac.build();
int ans=ac.query(str);
if(flag) printf("No\n");
else
printf("%s\n",ans==n-kk?str:"No");
}
return 0;
}