题解:HNOI2004 L语言 【AC自动机】

这个题目就是AC自动机的一个半板子题,难度不大(然而似乎没什么人用AC自动机)
似乎暴力跑的更快???(应该只是我水)

直接建AC自动机,然后跑就信了(喵喵喵???)

用广搜的样式(懒得慌STL好),DP的思想,然后就那样的找,最后能跑到的最后面的一个就是我们要找的长度(因为如果前面的有问题他是泡不到后面的,正确性一定可以保证)

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N=5010000;
int ch[N][26],fail[N],n,m,tot,vis[N],dep[N];
void insert(string s) {
	int l=s.size(),x,u=0;
	for(int i=0; i<l; ++i) {
		x=s[i]-'a';
		if(!ch[u][x]) ch[u][x]=++tot,dep[ch[u][x]]=dep[u]+1;
		u=ch[u][x];
	}
	vis[u]=1;
}
void get_fail() {
	queue <int> q;
	for(int i=0; i<26; ++i)
		if(ch[0][i]) q.push(ch[0][i]);
	while(!q.empty()) {
		int u=q.front();
		q.pop();
		for(int i=0; i<26; ++i) {
			if(ch[u][i]) {
				fail[ch[u][i]]=ch[fail[u]][i];
				q.push(ch[u][i]);
			} else
				ch[u][i]=ch[fail[u]][i];
		}
	}
}
int book[N];
int search(string s) {
	int u=0,l=s.size(),sum=0;
	book[0]=1;
	for(int i=0; i<l; ++i) {
		int x=s[i]-'a';
		u=ch[u][x];
		for(int j=u; j; j=fail[j]) {
			if(vis[j]&&book[i-dep[j]+1]) {
				book[i+1]=1;
				break;
			}
		}
	}
	for(int i=l; i; --i) if(book[i]) return i;

	return 0;
}
int main() {
	
	cin>>n>>m;
	for(int i=1; i<=n; ++i) {
		string ss;
		cin>>ss;
		insert(ss);
	}
	get_fail();
	for(int i=1; i<=m; ++i) {
		string s;
		cin>>s;
		cout<<search(s)<<endl;
		int l=s.size();
		for(int i=1; i<=l; ++i) book[i]=0;
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43464026/article/details/88387281