Taboo Kattis - taboo
题意:给一些01串,然后问有没有串没有包含这些01串的。如果有的话就输出,如果为无限长的话,就输出-1
分析:题目看错。。。做了好久,心好痛
这个题就是AC自动机建图,bad点都处理好了(和之前DNA处理一模一样)。然后拓扑判断一下是不是有环,如果有的话就-1,否者就输出最长串就行了。输出可以用dfs直接来,当然也可以用优雅的树dp思想
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 2e5+10;
string s[maxn];
char ans[maxn];
const int sz=3;
int flag=0,ansnum=0,tt=0;
int G[maxn][2];
void addedge(int u,int v,int w)
{
G[u][w]=v;
}
struct Trie
{
int next[maxn][3],fail[maxn],ed[maxn];
int root,L;
int newnode()
{
for(int i=0;i<2;i++)
next[L][i]=-1;
ed[L++]=0;
return L-1;
}
void init()
{
mem(fail,0);mem(ed,0);mem(in,0);
L=0;
root=newnode();
}
void sert(string buf)
{
int len=buf.length();
int now=root;
for(int i=0;i<len;i++)
{
if(next[now][buf[i]-'0']==-1)
next[now][buf[i]-'0']=newnode();
now=next[now][buf[i]-'0'];
}
ed[now]++;
}
void buildfail()
{
queue<int> Q;
fail[root]=root;
for(int i=0;i<2;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();
if(ed[fail[now]]) ed[now]=1;
for(int i=0;i<2;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 in[maxn],vis[maxn],inq[maxn],in2[maxn];
void dfs2(int now)
{
for(int i=0;i<2;i++)
{
int j=next[now][i];
if(ed[j]) continue;
in[j]++;in2[j]++;
if(in[j]==1) dfs2(j);
}
}
bool topo()//拓扑判环
{
mem(in,0);mem(inq,0);mem(vis,0);
dfs2(0);
queue<int> q;while(!q.empty()) q.pop();
if(in[0]) return 1;
q.push(0);
while(!q.empty()){
int now=q.front();q.pop();
for(int i=0;i<2;i++)
{
int j=next[now][i];
if(ed[j]) continue;
in[j]--;
vis[j]=1;
if(!in[j]) {inq[j]=1;q.push(j);}
}
}
for(int i=0;i<L;i++)
{
if(inq[i]!=vis[i]) return true;
}
return false;
}
int dp[maxn],to[maxn],maxx=0;
void dfs3(int now,int num)//求串的最大长度
{
if(num==maxx) {tt=1;return ;}
for(int i=0;i<2;i++)
{
int j=next[now][i];
if(ed[j]) continue;
dfs3(j,num+1);
if(tt){
ans[num]=i+'0';return ;
}
}
}
void dfs5(int now,int num)//找最大串
{
maxx=max(num,maxx);
for(int i=0;i<2;i++)
{
int j=next[now][i];
if(ed[j]) continue;
dfs5(j,num+1);
}
}
void query()
{
if(topo())
{
printf("-1");
return ;
}
mem(dp,0);mem(to,0);
queue<int> q; while(!q.empty()) q.pop();q.push(0);
dfs5(0,0);
dfs3(0,0);
printf("%s\n",ans);
}
};
Trie ac;
void init()
{
mem(ans,'\0');flag=0;tt=0;ansnum=0;
}
int main()
{
int n;
scanf("%d",&n);
ac.init();
init();
for(int i=0;i<n;i++){
cin>>s[i];
ac.sert(s[i]);
}
ac.buildfail();
ac.query();
return 0;
}
树dp输出
void dfs3(int now)
{
for(int i=0;i<2;i++)
{
int j=next[now][i];
if(ed[j]) continue;
dfs3(j);
to[now]=max(to[now],to[j]+1);
if(to[j]+dp[now]+1 == maxx)
addedge(now,j,i);
}
}
void query()
{
if(topo())
{
printf("-1");
return ;
}
mem(dp,0);mem(to,0);
queue<int> q; while(!q.empty()) q.pop();q.push(0);
while(!q.empty())
{
int now=q.front();q.pop();
for(int i=0;i<2;i++){
int j=next[now][i];
if(ed[j]) continue;
if(dp[j]<dp[now]+1)
dp[j]=dp[now]+1;
in2[j]--;
if(!in2[j]) {q.push(j);maxx=max(maxx,dp[j]);}
}
}
mem(G,-1);
dfs3(0);
int u=0;
while(dp[u]!=maxx)
{
if(G[u][0]!=-1)
{
printf("0");
u=G[u][0];
}
else {
printf("1");
u=G[u][1];
}
}
printf("\n");
}
};