首页 > 其他分享 >The ABCD Murderer

The ABCD Murderer

时间:2023-01-20 11:55:58浏览次数:60  
标签:ABCD tmp Murderer string insert int

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;
}
//直接找就行了

标签:ABCD,tmp,Murderer,string,insert,int
From: https://www.cnblogs.com/basicecho/p/17062631.html

相关文章