您的位置:首页 > 其它

AC自动机,Tarjan(ZOJ 3784,String of Infinity)

2017-04-26 18:26 253 查看
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
const int maxc = 26;
int MAXC;

int ch[maxn][maxc];
int val[maxn];
int sz;

int f[maxn];

vector<int>SET[maxn];
int pre[maxn];
int low[maxn];
int scc[maxn];
int dfs_clc;
int scc_cnt;
stack<int>s;

int vis[maxn];

struct Trie
{
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
val[0]=0;

char s[5];
s[1]='\0';
for(int c=0;c<MAXC;c++)
{
s[0]='a'+c;
insert(s);
val[sz-1]=0;
}
}

int idx(char c)
{
return c-'a';
}

void insert(char* s)
{
int l=strlen(s);
int u=0;
for(int i=0;i<l;i++)
{
int v=idx(s[i]);
if(!ch[u][v])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][v]=sz++;
}
u=ch[u][v];
}
val[u]=1;
}

void getfail()
{
queue<int>q;
f[0]=0;
for(int c=0;c<MAXC;c++)
{
f[ch[0][c]]=0;
q.push(ch[0][c]);
}
while(!q.empty())
{
int r=q.front();
q.pop();
for(int c=0;c<MAXC;c++)
{
int u=ch[r][c];
if(!u)
{
ch[r][c]=ch[f[r]][c];
continue;
}
if(val[u]) continue;
int v=f[r];
while(v&&val[ch[v][c]]) v=f[v];
f[u]=ch[v][c];
val[u]|=val[f[u]];
if(!val[u]) q.push(u);
}
}
}

void dfs(int u)
{
pre[u]=low[u]=++dfs_clc;
s.push(u);
for(int c=0;c<MAXC;c++) if(!val[ch[u][c]])
{
int v=ch[u][c];
if(!pre[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!scc[v]) low[u]=min(low[u],pre[v]);
}
if(pre[u]==low[u])
{
scc_cnt++;
while(1)
{
int x=s.top();
s.pop();
scc[x]=scc_cnt;
SET[scc_cnt].push_back(x);
if(x==u) break;
}
}
}

void handle()
{
for(int i=0;i<=sz;i++)
{
SET[i].clear();
pre[i]=0;
low[i]=0;
scc[i]=0;
}
dfs_clc=0;
scc_cnt=0;
while(!s.empty()) s.pop();
dfs(0);
}

int DFS(int u)
{
vis[u]=1;
int ret=0;
for(int c=0;c<MAXC;c++) if(scc[u]==scc[ch[u][c]])
{
int v=ch[u][c];
if(vis[v]) ret++;
if(!vis[v]) ret+=DFS(v);
}
return ret;
}

bool ok()
{
for(int i=0;i<=sz;i++) vis[i]=0;
handle();
for(int i=1;i<=scc_cnt;i++) if(DFS(SET[i][0])>1) return true;
return false;
}
}trie;

char str[1010];

void solve()
{
int N;
scanf("%d %d",&N,&MAXC);
trie.init();
while(N--)
{
scanf("%s",str);
trie.insert(str);
}
trie.getfail();
if(trie.ok()) puts("Yes");
else puts("No");
}

int main()
{
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: