[HNOI2006] 最短母串问题

Description

给定 (n le 12) 个字符串,要求找到一个最短的母串使得这 (n) 个字符串都是它的子串。如果有多个合法解则输出字典序最小的。每个字符串的长度不超过 (50)

Solution

(n) 个字符串建立 AC 自动机,对于每个串的末尾结点,打上标记。

建自动机的时候记得把标记下传一下

然后跑 BFS 即可,记录下每个点的来源,然后倒序输出

BFS 的时候先从小边走,以保证字典序

#include <bits/stdc++.h>
using namespace std;

const int N = 1005;

int ch[N][26],fi[N],val[N],n,m,t1,t2,t3,t4,ind;
pair<short,short> from[N][5005];
char chr[N][5005],vis[N][5005];

void ins(char *s,int px) {
	int len=strlen(s),p=0;
	for(int i=0;i<len;i++) {
		if(ch[p][s[i]-'A']==0) ch[p][s[i]-'A']=++ind;
		p=ch[p][s[i]-'A'];
	}
	val[p]|=1<<px;
}

void build() {
	queue <int> q;
	for(int i=0;i<26;i++) if(ch[0][i]) q.push(ch[0][i]);
	while(!q.empty()) {
		int p=q.front(); q.pop();
		for(int i=0;i<26;i++)
			if(ch[p][i]) fi[ch[p][i]]=ch[fi[p]][i],q.push(ch[p][i]),val[ch[p][i]]|=val[fi[ch[p][i]]];
			else ch[p][i]=ch[fi[p]][i];
	}
}

void printans(int p,int s) {
    if(p) {
        printans(from[p][s].first, from[p][s].second);
        cout<<chr[p][s];
    }
}

void bfs() {
    queue <pair<int,int> > q;
    q.push({0,0});
    vis[0][0]=1;
    while(q.size()) {
        pair<int,int> pr = q.front();
        q.pop();
        int p=pr.first, s=pr.second;
        for(int i=0;i<26;i++) {
            int p1=ch[p][i], s1=s|val[p1];
            if(!vis[p1][s1]) {
                q.push({p1,s1});
                from[p1][s1]={p,s};
                chr[p1][s1]=i+'A';
                vis[p1][s1]=1;
                if(s1==(1<<n)-1) {
                    printans(p1,s1);
                    return;
                }
            }
        }
    }
}

char str[N];

int main() {
	cin>>n;
	for(int i=1;i<=n;i++) cin>>str,ins(str,i-1);
	build();
	bfs();
}

原文地址:https://www.cnblogs.com/mollnn/p/13195275.html