The ABCD Murderer

The ABCD Murderer

思路

首先用ac自动机找到每一个点能向前最早到哪里,然后进行匹配就可以了

代码

//就是要用多少单词可以拼出这个单词
//这个CF有一个简化版
//当时是使用暴力过去的
//每次旋转一个最长的就可以了
//从后面开始选择,选一个最长的就可以了
#include <bits/stdc++.h>
using namespace std;
const int M=3e5+5;
int ch[M][26],fail[M],cnt[M],tot;
void insert(string s) {
int p=0,n=s.length();
for(int i=0;i<n;i++) {
int v=s[i]-'a';
if(ch[p][v]==0)ch[p][v]=++tot;
p=ch[p][v];
}
cnt[p]=max(cnt[p],n);
}//要不就直接记录长度吧
int last[M];
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 now=q.front();
q.pop();
for(int i=0;i<26;i++) {
if(ch[now][i]) {
fail[ch[now][i]]=ch[fail[now]][i];
q.push(ch[now][i]);
if(cnt[fail[ch[now][i]]])last[ch[now][i]]=fail[ch[now][i]];
else last[ch[now][i]]=last[fail[ch[now][i]]];
}
else ch[now][i]=ch[fail[now]][i];
}
}
}
int a[M];
void query(string s) {
int now=0,n=s.length();
for(int i=0;i<n;i++) {
now=ch[now][s[i]-'a'];
for(int j=now;j;j=last[j])
if(cnt[j]) {
a[i]=i-cnt[j]+1;//能够达到哪里
break;
}
}
}
int main() {
memset(a,0x3f,sizeof(a));
int n;cin>>n;
string s;cin>>s;
for(int i=1;i<=n;i++) {
string t;cin>>t;
insert(t);
}
build();
query(s);
n=s.length();
int l=a[n-1],r=n-2;
int ans=1;
while(1) {
if(l==0)break;
int tmp=n;
for(int i=r;i>=l-1;i--)
tmp=min(tmp,a[i]);
r=l-1;
l=tmp;
if(tmp==n)return cout<<-1,0;
ans++;
}
cout<<ans<<endl;
return 0;
}
//直接找就行了
posted @   basicecho  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示