题意:给s个禁止子串,求不含他们的最长串。
思路:用这s个禁止串建一个 AC自动机,那么这些串的尾节点表示禁止节点。然后DFS判断是否存在环(为环就无限长了),在DFS的时候顺便记录下跑的路径,在输出字符串的时候就方便了。
代码:
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
#define nn 100040
bool loop;//判断环
int road[nn];//记录路径
int vis[nn], dp[nn];//dp[i]表示以i节点结尾的字符串的长度
struct aho
{
int ch[nn][26];
int last[nn], val[nn], f[nn];
int sz;
void init()
{
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
val[0] = 0;
}
int idx(char c)
{
return c - 'A';
}
void insert(char* s, int m)
{
int n = strlen(s), u = 0;
for (int i = 0; i<n; i++)
{
int c = idx(s[i]);
if (!ch[u][c])
{
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = 1;//标记所有不能走到的点
}
void get_f(int m)
{
queue<int>q;
f[0] = 0;
for (int c = 0; c<m; c++)
{
int u = ch[0][c];
if (u)
{
f[u] = 0;
q.push(u);
last[u] = 0;
}
}
while (!q.empty())
{
int r = q.front(); q.pop();
for (int c = 0; c<m; c++)
{
int u = ch[r][c];
if (!u)
{
ch[r][c] = ch[f[r]][c];
continue;
}
q.push(u);
int v = f[r];
while (v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
}
int dfs(int now, int m)
{
if (loop) return 0;
if (dp[now] != -1) return dp[now];
dp[now] = 0;
for (int i = m - 1; i >= 0; i--)
{
if (!val[ch[now][i]])
{
if (vis[ch[now][i]])//发现回路
{
loop = 1;
return 0;
}
else
{
vis[ch[now][i]] = 1;
if (dp[now]<1 + dfs(ch[now][i], m))
{
dp[now] = 1 + dp[ch[now][i]];
road[now] = i; //记录路径,表示now节点选的下一个节点位置
}
vis[ch[now][i]] = 0;
}
}
}
return dp[now];
}
};
aho t;
char str[100];
int main()
{
int T, n, m;
scanf("%d", &T);
while (T--)
{
t.init();
scanf("%d%d", &n, &m);
for (int i = 0; i<m; i++)
{
scanf("%s", str);
t.insert(str, n);
}
t.get_f(n);
loop = 0;
memset(vis, 0, sizeof(vis));
memset(dp, -1, sizeof(dp));
vis[0] = 1;
t.dfs(0, n);
if (loop || !dp[0]) printf("No\n");
else
{
int now = 0;
for (int i = 0; i<dp[0]; i++)
{
printf("%c", road[now] + 'A');
now = t.ch[now][road[now]];
}
printf("\n");
}
}
return 0;
}