以前的题:给n个串,问是否有一个串,包含了其他所有串。
后缀自动机解法,练下模板。。(虽然这题用AC自动机加标记也能过但时间大概2秒多。但我们通过分析AC自动机则必须使用全部的字符串来建立自动机,加上乘个memset[26]是很容易被卡掉的。用后缀自动机的话只会用最长的那个字符串来建立自动机,然后对n-1个字符串分别从sam的0节点开始向下跑即可,如果能跑完就说是母串的某个后缀的前缀,这样速度就快很多了。)
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
const int MAXN = 2*1e5 + 8;
string s;
struct SAM{
int ch[MAXN][26], pre[MAXN], step[MAXN],last, tot;
void init(){
last = tot = 0;
memset(ch[0], -1, sizeof ch[0]);
pre[0] = -1; step[0] = 0;
}
void extend(int c){
int p = last, np = ++tot;
step[np] = step[p] + 1;
memset(ch[np], -1, sizeof ch[np]);
while(p!=-1 && ch[p][c] == -1) ch[p][c] = np, p = pre[p];
if(p == -1) pre[np] = 0;
else{
int q = ch[p][c];
if(step[q] != step[p] + 1){
int nq = ++tot;
memcpy(ch[nq], ch[q], sizeof ch[q]);
step[nq] = step[p] + 1;
pre[nq] = pre[q];
pre[q] = pre[np] = nq;
while(p!=-1 && ch[p][c] == q) ch[p][c] = nq, p = pre[p];
}
else pre[np] = q;
}
last = np;
}
void build(string s)
{
init();
for(int i = 0; i < s.size(); i++) extend(s[i] - 'a');
}
bool _find(const string &s){
int sz = s.size(), u = 0, tmp = 0, c, i, res = 0;
for(i = 0; i < sz; i++){
c = s[i] - 'a';
if(ch[u][c]!=-1) u = ch[u][c];
else return false;
}
return true;
}
} sam;
string str[MAXN];
int main()
{
ios::sync_with_stdio(false); cin.tie(0);
int T, n, sz, i, len, ind;
bool ans;
cin >> T;
while(T--){
cin >> n;
len = 0;
for(i = 0; i < n; i++){
cin >> str[i];
if(len < str[i].size()){
len = str[i].size();
ind = i;
}
}
s.clear();
s += str[ind];
sam.build(s);
ans = true;
for(i = 0; i < n; i++){
if(i == ind) continue;
if(!sam._find(str[i])){
ans = false;
break;
}
}
if(ans) cout << str[ind] <<endl;
else cout <<"No"<<endl;
}
return 0;
}