思路
首先用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;
}
//直接找就行了
标签:ABCD,tmp,Murderer,string,insert,int
From: https://www.cnblogs.com/basicecho/p/17062631.html