题目描述
给出n个字符串,求是否存在一个无限长度的字符串使这n个字符串都不是它的子串。
思路
当你想到这道题可能与Trie图有关,你就成功一半了。我们考虑在Trie图上如何求解答案,首先如果说存在这样一个无限长的子串,那么显然在Trie图上形成了一条环,并且这条环不经过每个串的结尾,而且这个环一定能从根节点开始访问。对于求环我们可以用dfs,即用两个数组vis和v,vis表示是否访问过,v表示这个节点是否在搜索的栈中,如果由环直接输出即可。
代码
#include<bits/stdc++.h> using namespace std; int ch[30010][2],tot=1; bool ed[30010]; void insert(char *s) { int u=1,len=strlen(s); for(int i=0;i<len;i++) { int c=s[i]-'0'; if(!ch[u][c])ch[u][c]=++tot; u=ch[u][c]; } ed[u]=1; } int nxt[30010]; void getfail() { for(int i=0;i<=1;i++) ch[0][i]=1; queue<int>q; q.push(1);nxt[1]=0; while(!q.empty()) { int u=q.front();q.pop(); for(int i=0;i<=1;i++) { if(!ch[u][i])ch[u][i]=ch[nxt[u]][i]; else { int v=nxt[u]; q.push(ch[u][i]); while(v&&!ch[v][i])v=nxt[v]; nxt[ch[u][i]]=ch[v][i]; } } } for(int i=1;i<=tot;i++) { int v=nxt[i]; while(v)ed[i]|=ed[v],v=nxt[v]; } } bool vis[30010],v[30010]; void dfs(int u) { vis[u]=1;v[u]=1; for(int i=0;i<=1;i++) { if(v[ch[u][i]]) { printf("TAK"); exit(0); } else if(!ed[ch[u][i]]&&!vis[ch[u][i]]) dfs(ch[u][i]); } v[u]=0; } char s[30010]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf(" %s",s); insert(s); } getfail(); // for(int i=1;i<=tot;i++) // cout<<i<<' '<<nxt[i]<<endl; dfs(0); printf("NIE"); }