您的位置:首页 > 其它

HDU 6208 The Dominator of Strings 后缀自动机

2017-10-01 20:49 459 查看

The Dominator of Strings

Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)



[align=left][b]Problem Description[/b][/align]
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.

[align=left][b]Input[/b][/align]
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.

[align=left][b]Output[/b][/align]
For each test case, output a dominator if exist, or No if not.

[align=left][b]Sample Input[/b][/align]

3
10
you
better
worse
richer
poorer
sickness
health
death
faithfulness
youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness
5
abc
cde
abcde
abcde
bcde
3
aaaaa
aaaab
aaaac

[align=left][b]Sample Output[/b][/align]

youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness
abcde
No

[b]题意:[/b]
  给你n个串,问你是否村你在一个串,包含了其他所有串
[b]题解:[/b]
  必然是最长串,
  将 其建立后缀自动机, 并将剩余的串与其匹配,也就是最长公共字串 长度  
  ios::sync_with_stdio(false); cin.tie(0); 这句话 可以加快C++输入输出,不加就TLE

#include <bits/stdc++.h>
inline long long read(){long long x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
using namespace std;

const int N = 2e5+7;
const long long mod = 1000000007;

int isPlus[N * 2],endpos[N * 2];int d[N * 2];
int tot,slink[2*N],trans[2*N][28],minlen[2*N],maxlen[2*N],pre;
int newstate(int _maxlen,int _minlen,int* _trans,int _slink){
maxlen[++tot]=_maxlen;minlen[tot]=_minlen;
slink[tot]=_slink;
if(_trans)for(int i=0;i<26;i++)trans[tot][i]=_trans[i];
return tot;
}
int add_char(char ch,int u){
int c=ch-'a',v=u;
int z=newstate(maxlen[u]+1,-1,NULL,0);
isPlus[z] = 1;
while(v&&!trans[v][c]){trans[v][c]=z;d[z]+=1;v=slink[v];}
if(!v){ minlen[z]=1;slink[z]=1;return z;}
int x=trans[v][c];
if(maxlen[v]+1==maxlen[x]){slink[z]=x;minlen[z]=maxlen[x]+1;return z;}
int y=newstate(maxlen[v]+1,-1,trans[x],slink[x]);
slink[z]=slink[x]=y;minlen[x]=minlen[z]=maxlen[y]+1;
while(v&&trans[v][c]==x){trans[v][c]=y;d[x]--,d[y]++;v=slink[v];}
minlen[y]=maxlen[slink[y]]+1;
return z;
}
void init_sam() {
for(int i = 1; i <= tot; ++i)
for(int j = 0; j < 26; ++j) trans[i][j] = 0;
pre = tot = 1;
}
int T,n;
string a
;
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin>>T;
while(T--) {
cin>>n;
int mx = 0,flag = 0;int ok = 0;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
if(a[i].length() > mx) {
mx = a[i].length();
flag = i;
}
}
init_sam();
for(int i = 0; i < mx; ++i)
pre = add_char(a[flag][i],pre);
for(int i = 1; i <= n; ++i) {
if(i == flag) continue;
int now = 0;
int p = 1;
int ans = 0;
for(int j = 0; j < a[i].length(); ++j) {
if(trans[p][a[i][j]-'a']) {
now += 1;
p = trans[p][a[i][j]-'a'];
}else {
while(p) {
p = slink[p];
if(trans[p][a[i][j]-'a']) break;
}
if(!p) p = 1,now = 0;
else {
now = maxlen[p] + 1;
p = trans[p][a[i][j]-'a'];
}
}
ans = max(ans,now);
}
if(ans != a[i].length()) {
cout<<"No"<<endl;
ok = 1;
break;
}
}
if(!ok) cout<<a[flag]<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: