1 条题解
-
0
思路
合并历史为AC状态与已覆盖模式位集,按字符递增进行BFS并只保留首次到达即可同时实现最短和最小字典序;最多601×4096状态,父指针回溯不保存每条路径字符串;重复词及fail输出位均须处理。
参考程序(C++11)
#include <bits/stdc++.h> using namespace std; int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int n;cin>>n;vector<array<int,26>>g(1);vector<int>f(1),out(1);set<int>alphabet;for(int i=0;i<n;i++){string s;cin>>s;int v=0;for(char c:s){int x=c-'A';alphabet.insert(x);if(!g[v][x]){int u=g.size();g[v][x]=u;g.push_back({});f.push_back(0);out.push_back(0);}v=g[v][x];}out[v]|=1<<i;}queue<int>q;for(int c:alphabet)if(g[0][c])q.push(g[0][c]);while(!q.empty()){int v=q.front();q.pop();out[v]|=out[f[v]];for(int c:alphabet)if(g[v][c]){int u=g[v][c];f[u]=g[f[v]][c];q.push(u);}else g[v][c]=g[f[v]][c];}int nodes=g.size(),full=(1<<n)-1,total=nodes*(1<<n);vector<int>prev(total,-2),que;vector<unsigned char>letter(total);que.reserve(total);prev[0]=-1;que.push_back(0);int goal=-1;for(size_t h=0;h<que.size()&&goal<0;h++){int id=que[h],v=id%nodes,mask=id/nodes;for(int c:alphabet){int u=g[v][c],m=mask|out[u],next=m*nodes+u;if(prev[next]!=-2)continue;prev[next]=id;letter[next]=c;que.push_back(next);if(m==full){goal=next;break;}}}string ans;for(int id=goal;prev[id]!=-1;id=prev[id])ans+=char('A'+letter[id]);reverse(ans.begin(),ans.end());cout<<ans<<'\n';}
- 1