警示后人 80pts
查看原帖
警示后人 80pts
316358
不知名用户楼主2024/1/1 18:12

https://www.luogu.com.cn/record/141668600

注意 Trie 每个点包含的状态记得或上 fail 的状态。我下面的代码要加上第 28 行才能 AC。

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

const int N = 610;

int t[N][26], idx = 1, fail[N], c[N], v[N][1<<12], f1[N][1<<12], f2[N][1<<12];
queue<int>q1, q2;
char str[N], ans[N];int top;
void ins(int id)
{
	int i, p = 1, l;
	cin>>str+1, l = strlen(str+1);
	for(i=1;i<=l;i++)
	{
		if(!t[p][str[i]-'A']) t[p][str[i]-'A'] = ++idx;
		p = t[p][str[i]-'A'];
	}
	c[p] |= id;
}
void build()
{
	int i;
	for(i=0;i<26;i++) t[0][i] = 1;fail[1] = 0;
	queue<int>q;q.push(1);
	while(!q.empty())
	{
		int d = q.front();q.pop();
		c[d] |= c[fail[d]];//这句话很重要!
		for(i=0;i<26;i++)
			if(t[d][i]) fail[t[d][i]] = t[fail[d]][i], q.push(t[d][i]);
			else t[d][i] = t[fail[d]][i];
	}
}

int main()
{
	int n, i;
	cin>>n;
	for(i=1;i<=n;i++) ins(1<<i-1);
	build();
	q1.push(1), q2.push(0);
	v[1][0] = 1;
	while(!q1.empty())
	{
		int d1 = q1.front(), d2 = q2.front();q1.pop();q2.pop();
		if(d2==((1<<n)-1))
		{
			while(d1!=1||d2!=0)
			{
				ans[++top] = v[d1][d2];
				int e1 = f1[d1][d2], e2 = f2[d1][d2];
				d1 = e1, d2 = e2;
			}
			while(top) cout<<ans[top--];
			break;
		}
		for(i=0;i<26;i++)
		{
			int e1 = t[d1][i];int e2 = d2 | c[e1];
			if(v[e1][e2]) continue;
			v[e1][e2] = i + 'A';
			f1[e1][e2] = d1, f2[e1][e2] = d2;
			q1.push(e1), q2.push(e2);
		}
	}
	return 0;
}
2024/1/1 18:12
加载中...