The Dominator of Strings
Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 753 Accepted Submission(s): 219
Total Submission(s): 753 Accepted Submission(s): 219
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自动机
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <string>
#include <cstring>
#include <ctime>
#include <queue>
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N = 100010;
const int M = 26;
struct AC
{
int ch[N][M], fail[N], val[N];
int sz;
void init()
{
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
memset(val, 0, sizeof(val));
}
int idx(char c)
{
return c - 'a';
}
void add(char *s)
{
int n, now = 0;
n = strlen(s);
for (int i = 0; i < n; i++)
{
int id = idx(s[i]);
if (ch[now][id] == 0)
{
memset(ch[sz], 0, sizeof(ch[sz]));
ch[now][id] = sz++;
}
now = ch[now][id];
}
val[now]++;
}
void Build()
{
queue<int>que;
fail[0] = 0;
for (int i = 0; i < M; i++)
{
int u = ch[0][i];
if (u)
{
fail[u] = 0;
que.push(u);
}
}
while (!que.empty())
{
int r = que.front();
que.pop();
for (int c = 0; c < M; c++)
{
int u = ch[r][c];
if (!u)
{
continue;
}
que.push(u);
int v = fail[r];
while (v && !ch[v][c])
{
v = fail[v];
}
fail[u] = ch[v][c];
}
}
}
int Query(char *s)
{
int n, now = 0, ans = 0;
n = strlen(s);
for (int i = 0; i < n; i++)
{
int id = idx(s[i]);
while (now && !ch[now][id])
{
now = fail[now];
}
now = ch[now][id];
int t = now;
while (t && val[t] != -1)
{
ans += val[t];
val[t] = -1;
t = fail[t];
}
}
return ans;
}
} ac;
char s[100010], a[100010];
int main()
{
ios::sync_with_stdio(false);
int T, n;
cin >> T;
while (T--)
{
cin >> n;
if (n == 0)
{
cout << "No" << endl;
continue;
}
int maxx = 0, hh = n, len;
ac.init();
while (hh--)
{
cin >> a;
len = strlen(a);
ac.add(a);
if (len > maxx)
{
maxx = len;
strcpy(s, a);
s[len] = '\0';
}
}
ac.Build();
if (ac.Query(s) == n)
{
cout << s << endl;
}
else
{
cout << "No" << endl;
}
}
return 0;
}