【Codeforces 149E】Martian Strings | KMP、AC自动机

想刷下AC自动机的题,搜出来个这个

但是用KMP过了..

题目链接:https://codeforces.com/contest/149/problem/E

题目大意:

给出一个t串,和m个s串,对于每个s串判断是否可以在t串中找出两个子串

使得T[a,b] + T[c,d] = s

输出所有可以的s串的个数

题目思路:

Thinking_1

嗯...稍后会更新AC自动机的写法

考虑kmp,pre_i代表s串前缀与t串前i个前缀匹配的最大长度

预处理好pre数组之后

将s串翻转,处理s串后缀与t串后i个匹配的长度,然后与pre[i-1]相加看是否已经大于等于s串的长度

注意一些细节问题,必须要分成两个那么就不可以单独一个

注意一些特判即可

Code_1

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
//#include <bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
#include<algorithm>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pp;
const ll INF=1e17;
const int Maxn=2e7+10;
const int maxn =1e6+10;
const int mod=1e9+7;
const int Mod = 1e9+7;
///const double eps=1e-10;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;

int nxt[maxn];
int getnext(string p){
    int len = p.size();
    nxt[0] = -1;
    for(int i=0,j=-1;i<len;i++){
        while(~j&&p[i+1] != p[j+1]) j = nxt[j];
        if(p[i+1] == p[j+1]) j++;
        nxt[i+1] = j;
    }
}
int pre[maxn];///前缀匹配的最大长度
int kmp(string s,string t){
    pre[0] = -1;
    int slen =  s.size(),tlen = t.size();
    getnext(s);
    for(int i=0,j=-1;i<tlen;i++){
        while(~j&&t[i]!=s[j+1]){
            j = nxt[j];
        }
        if(t[i] == s[j+1]) j++;
        if(i) pre[i] = max(pre[i-1],j);
        else pre[i] = j;
    }
    reverse(s.begin(),s.end());
    getnext(s);
    for(int i=tlen-1,j =-1;i>0;i--){
        while(~j&&t[i] != s[j+1]) j=nxt[j];
        if(t[i] == s[j+1]) j++;

        if(pre[i-1]>-1&&j+pre[i-1]+2>=slen) return 1;
    }
    return 0;
}
string s,t;
int main(){
    cin>>t;
    read(n);
    int ans = 0;
    for(int i=1;i<=n;i++){
        cin>>s;
        if(s.size()>1)
            ans += kmp(s,t);
    }
    printf("%d\n",ans);
    return 0;
}
/**
4
2
abcd
cdab
abcdab

ababab
**/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/107558594