【解题参考blog】http://blog.csdn.net/acm_10000h/article/details/48878645
【题意】给定K和N,表示有K种不同的字符,N个禁止串,求一个最长的串使得该串不包含任何禁止串为子串。如果存在循环或者不能构成的话,输出No!
【解题方法】实际上就是Trie图上的最长路,先对模式串建立AC自动机,之后在AC自动机上跑最长路。无限长的情况就是trie图形成了环,这个dfs判环即可!
【代码君】
//
//Created by just_sort 2016/10/13
//Copyright (c) 2016 just_sort.All Rights Reserved
//
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 55555;
const int maxm = 26;
struct Acautomata{
int ch[maxn][maxm],val[maxn],fail[maxn],root,sz;
int newnode(){
val[sz] = 0;
memset(ch[sz], 0, sizeof(ch[sz]));
return sz++;
}
void init(){
sz = 0;
root = newnode();
}
void insert(char *s,int v){
int len = strlen(s);
int u = root;
for(int i = 0; i < len; i++){
int now = s[i] - 'A';
if(!ch[u][now]){
ch[u][now] = newnode();
}
u = ch[u][now];
}
val[u] = v;
}
void build(){
queue <int> q;
fail[0] = 0;
for(int i = 0; i < maxm; i++){
int u = ch[0][i];
if(u){
q.push(u);
fail[u] = 0;
}
}
while(q.size())
{
int u = q.front(); q.pop();
for(int i = 0; i < maxm; i++){
int v = ch[u][i];
if(!v){
ch[u][i] = ch[fail[u]][i]; continue;
}
q.push(v);
int j = fail[u];
while(j && !ch[j][i]) j = fail[j];
fail[v] = ch[j][i];
val[v] |= val[fail[v]];
}
}
}
}ac;
int n,m;
int vis1[maxn],vis2[maxn],dp[maxn],path[maxn][2];
bool dfs1(int u)
{
vis2[u] = 1;
for(int i = 0; i < n; i++)
{
int v = ac.ch[u][i];
if(vis1[v]) return 1;
if(!vis2[v] && !ac.val[v])
{
vis1[v] = 1;
if(dfs1(v)) return true;
vis1[v] = 0;
}
}
return false;
}
int dfs2(int u)
{
if(vis1[u]) return dp[u];
vis1[u] = 1;
dp[u] = 0;
for(int i = n - 1; i >= 0; i--)
{
if(!ac.val[ac.ch[u][i]])
{
int tmp = dfs2(ac.ch[u][i]) + 1;
if(dp[u] < tmp)
{
dp[u] = tmp;
path[u][0] = ac.ch[u][i];
path[u][1] = i;
}
}
}
return dp[u];
}
void print_path(int u)
{
if(path[u][0] == -1) return ;
printf("%c", 'A' + path[u][1]);
print_path(path[u][0]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ac.init();
scanf("%d%d",&n,&m);
for(int i = 0; i < m; i++){
char op[55];
scanf("%s",op);
ac.insert(op,1);
}
ac.build();
memset(vis1, 0, sizeof(vis1));
memset(vis2, 0, sizeof(vis2));
vis1[0] = 1;
if(dfs1(0))
{
printf("No\n");
}
else{
memset(vis1, 0, sizeof(vis1));
memset(path, -1, sizeof(path));
if(dfs2(0) == 0)
{
printf("No\n");
}
else
{
print_path(0);
puts("");
}
}
}
return 0;
}