牛课多校F-TypingPractise(KMP或者AC自动机)

传送门

思路:用KMP和AC思路是一样的。ac的思路就是跑文本串,记录下每个节点的最小值,这样会省时间,因为fail指针的存在,我们不需要管模式串,kmp的话就是每个模式串都要匹配,取最小值;

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int val[N];
int nxt[500010][26], fail[500010];
stack<int> st;
bool vis[500010];
 
struct Trie{
    int root, L;
    int newnode(){
        for(int i=0; i<27; i++)
            nxt[L][i]=-1;
 
        return L++;
    }
    void init(){
        L=0;
        memset(val, 0x3f, sizeof val);
        root=newnode();
    }
 
    void Insert(char buf[]){
        int len=strlen(buf);
 
        int now=root;
        val[now]=min(len, val[now]);
        for(int i=0; i<len; i++){
            if(nxt[now][buf[i]-'a']==-1)
                nxt[now][buf[i]-'a']=newnode();
            now=nxt[now][buf[i]-'a'];
            val[now]=min(val[now], len-i-1);
        }
    }
    void build(){
        queue<int>Q;
        fail[root]=root;
        for(int i=0; i<26; i++)
            if(nxt[root][i]==-1)
                nxt[root][i]=root;
            else{
                fail[nxt[root][i]]=root;
                Q.push(nxt[root][i]);
            }
 
        while(!Q.empty()){
            int now=Q.front();
            Q.pop();
            for(int i=0; i<26; i++)
                if(nxt[now][i]==-1)
                    nxt[now][i]=nxt[fail[now]][i];
                else{
                    fail[nxt[now][i]]=nxt[fail[now]][i];
                    Q.push(nxt[now][i]);
                }
        }
    }
    void query(char buf[]){
        int len=strlen(buf);
        int now=root;
        for(int i=0; i<len; i++){
            if(buf[i]=='-'){
                if(!st.empty()) st.pop();
                if(!st.empty()) now=st.top();
                else now=0;
            }
            else{
                now=nxt[now][buf[i]-'a'];
                st.push(now);
            }
            int tmp=now, ans=val[now];
            while(tmp!=root&&!vis[tmp]){
                tmp=fail[tmp];
                ans=min(val[tmp], ans);
                vis[tmp]=true;
            }
            printf("%d\n", ans);
        }
    }
 
};
int n;
char s[5][N], txt[N];
 
int main(){
    Trie ac;
    ac.init();
    scanf("%d", &n);
    for(int i=1; i<=n; i++){
        scanf("%s", s[i]);
        ac.Insert(s[i]);
    }
    ac.build();
    scanf("%s", txt);
    printf("%d\n", val[0]);
    ac.query(txt);
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int INF=0x3f3f3f3f;
int nxt[5][N], n, length[5], pos[5][N];
char txt[N], s[5][N];
 
void get_nxt(char str[], int m, int id){
    int i, j;
    j=nxt[id][0]=-1; i=0;
    while(i<m){
        while(-1!=j && str[i]!=str[j]) j=nxt[id][j];
        if(str[++i]==str[++j])
            nxt[id][i]=nxt[id][j];
        else
            nxt[id][i]=j;
    }
}
 
int main(){
    scanf("%d", &n);
 
    for(int i=1; i<=n; i++){
        scanf("%s", s[i]);
        length[i]=strlen(s[i]);
        get_nxt(s[i], length[i], i);
    }
    scanf("%s", txt);
 
    int mn=INF;
    for(int i=1; i<=n; i++) mn=min(length[i], mn);
    printf("%d\n", mn);
 
    int len=strlen(txt), id=0;
    for(int i=0; i<len; i++){
        if(txt[i]=='-'){
            if(id) id--;
            mn=INF;
            for(int j=1; j<=n; j++)
                mn=min(mn, length[j]-pos[j][id]);
            printf("%d\n", mn);
        }
        else{
            int tmp; mn=INF;
            for(int j=1; j<=n; j++){
                tmp=pos[j][id];
                while(tmp!=-1 && s[j][tmp]!=txt[i]) tmp=nxt[j][tmp];
                pos[j][id+1]=++tmp;
                mn=min(mn, length[j]-tmp);
            }
            printf("%d\n", mn);
            id++;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/du_lun/article/details/81749835
今日推荐