非主流做法 , 此题就不提示了。
看到此题 , Fuxey的第一感觉 , 这玩意我以前见过啊 , AC自动机上的动态规划。 中午回学校啪啪敲了一份AC自动机上的状压DP。
WA WA WA
然后检查 , 代码。 起初我认为同层(即同一个状态S) 互相影响并不会更优 , 所以不会影响答案, 然而需要考虑同层的转化。
不要紧 , Dijkstra上
TLE……
然而n^2的Dijkstra并不能过 , 优先队列优化一下呗。 然而A了……
(Fuxey建议大家还是写主流的状压DP写法 , 除非想练写AC自动机 )
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cassert>
using namespace std;
const int maxn = 12;
const int maxlen = 51;
const int sigmaSize = 26;
const int INF = 0x3f3f3f3f;
const int maxnode = maxlen*maxn;
int n;
char s[maxlen];
int d[maxnode][1<<maxn] , loop[maxnode][1<<maxn];
int pre[maxnode][1<<maxn];
__inline int id(char c) { return c-'A'; }
struct ACaut
{
int n;
queue<int> q;
int g[maxnode][sigmaSize];
int mark[maxnode] , v[maxnode] , f[maxnode];
vector<int> l[maxnode] , r[maxnode]; int book[maxnode];
void init() { n = 0; }
void add(int num)
{
int len = strlen(s) , u = 0;
for(int i=0;i<len;i++)
{
int c = id(s[i]);
if(!g[u][c])
{
g[u][c] = ++n;
mark[n] = f[n] = 0;
memset(g[n] , 0 , sizeof(g[n]));
}
u = g[u][c];
}
mark[u] |= 1<<(num-1);
}
void getFail()
{
mark[0] = v[0] = f[0] = 0;
for(int i=0;i<sigmaSize;i++)
{
int t = g[0][i];
if(!t) continue;
q.push(t);
if(mark[t]) v[t] = mark[t];
}
while(!q.empty())
{
int now = q.front(); q.pop();
for(int i=0;i<sigmaSize;i++)
{
int t = g[now][i] , j;
if(!t)
{
g[now][i] = g[f[now]][i];
continue;
}
else q.push(t);
for(j=f[now];j && !g[j][i];j = f[j]) ;
f[t] = g[j][i]?g[j][i]:0;
v[t] = v[f[t]];
if(mark[t]) v[t] |= mark[t];
}
}
}
void dpInit()
{
for(int i=0;i<=n;i++) memset(d[i] , -1 , sizeof(d[i]));
}
void dp(int s)
{
if(s==(1<<::n)-1) { for(int i=0;i<=n;i++) d[i][s] = 0; return; }
for(int i=0;i<=n;i++) l[i].clear() , r[i].clear();
for(int u=0;u<=n;u++)
{
int& now = d[u][s] = INF; book[u] = 0;
for(int i=0;i<sigmaSize;i++)
{
int t = g[u][i];
if((s|v[t]) == s && t!=u) l[t].push_back(u) , r[t].push_back(i);
else if(d[t][s|v[t]]+1 < now) now = d[t][s|v[t]]+1 , pre[u][s] = i;
}
}
priority_queue<pair<int, int> > pq;
for(int i=0;i<=n;i++) if(d[i][s]!=INF) pq.push(make_pair(-d[i][s], i));
while(pq.size())
{
int now = pq.top().second , v = -pq.top().first; pq.pop();
if(d[now][s]!=v) continue;
for(int i=0;i<l[now].size();i++)
{
int k = l[now][i];
if(d[k][s] > v+1 || (d[k][s]==v+1 && pre[k][s] > r[now][i]))
{
pre[k][s] = r[now][i];
if(d[k][s] == v+1) continue;
d[k][s] = v+1;
pq.push(make_pair(-d[k][s], k));
}
}
}
}
void print()
{
int s = 0;
for(int i=0 , j=1;j<=d[0][0];j++)
{
printf("%c" , 'A'+pre[i][s]);
i = g[i][pre[i][s]];
s |= v[i];
}
}
}solver;
int main()
{
cin>>n;
solver.init();
for(int i=1;i<=n;i++)
{
scanf("%s" , s);
solver.add(i);
}
solver.getFail();
for(int i=(1<<n)-1;i>=0;i--) solver.dp(i);
solver.print( );
return 0;
}
附上最卡时限的数据:
TestData 9:
Input:
12
AABBBABBBBBAAAAABABBBAAABBABBAABABAABAAABAAA
AAABBBAAABABBBABBBABABAABAABABBBBABBBAABBA
BBBBABAABABBBABABABBBAAABBABBBABAABBBAAABABBABB
BABBBAABBABABBABBBAAABABAABBAA
BBAABAAABAABBBBBABBBBBAABBBBABBBBBBABAAAAABAA
ABAABBBBBABBAABAABBAAABABBBAAABBBBBABAAB
ABBBBBABBAABAABBAAABABBBAAABBBBBABAABAAAAABBBBBAB
BAAABABAABBAA
BAABAAABABBBBBABBBABAAAAAABBAAABBBAAABABBB
AAABABBABBBAAAABBBBAAAAABBBBABBBBABBAABAAABAAAB
AAABABBBAAABBBBBABAABAAAAABBBBBABABABBAAABABAB
BBAABBBBABABBAABABABBBBBBBBABAAABABAAAAA
Output:
BAABAAABABBBBBABBBABAAAAAABBAAABBBAAABABBBABBBABABAABAABABBBBABBBAABBABABBABBBAAABABAABBAABAAABAABBBBBABBBBBAABBBBABBBBBBABAAAAABAABBBBBABBAABAABBAAABABBBAAABBBBBABAABAAAAABBBBBABABABBAAABABABBAABBBBABABBAABABABBBBBBBBABAAABABAAAAABBBBABAABABBBABABABBBAAABBABBBABAABBBAAABABBABBBAAAABBBBAAAAABBBBABBBBABBAABAAABAAABBBABBBBBAAAAABABBBAAABBABBAABABAABAAABAAA