test20181020 B君的第二题

题意


分析

考场70分

一看就是裸的kmp,直接打上去。

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read()
{
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return data*w;
}
template<class T> il T read(T&x)
{
    return x=read<T>();
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1e5+8;
char s[MAXN],t[MAXN];
int n,m;
int nx[MAXN];
int f[MAXN],len;

int main()
{
  freopen("xining.in","r",stdin);
  freopen("xining.out","w",stdout);
    scanf("%s",s+1);
    n=strlen(s+1);
    scanf("%s",t+1);
    m=strlen(t+1);
    
    for(int i=2;i<=n;++i)
    {
        int p=nx[i-1];
        while(p&&s[p+1]!=s[i])
            p=nx[p];
        if(s[p+1]==s[i])
            ++p;
        nx[i]=p;
    }
    
    printf("%d\n",n);
    for(int i=1;i<=m;++i)
    {
        if(t[i]=='-')
        {
            --len;
            if(len<0)
                len=0;
            printf("%d\n",n-f[len]);
            continue;
        }
//      cerr<<"pro "<<i<<endl;
        int p=f[len];
//      cerr<<" p="<<p<<endl;
        while(p&&s[p+1]!=t[i])
            p=nx[p];
        if(s[p+1]==t[i])
            ++p;
        f[++len]=p;
//      cerr<<" p="<<p<<endl;
        printf("%d\n",n-p);
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

结果TLE了。
实际上时间复杂度\(O(n^2)\)

标解

这道题能卡kmp,是因为往回跳next的时候复杂度没了保证。

退格操作可以让匹配长度剧增,这与kmp要满足长度增加量最多为文本串的长度的性质不符,所以要被卡。

B君:可以前n/2都是a,然后后面一个-一个b交替出现,就可以把kmp卡成n方的了。

但是AC自动机中的一个构建优化是把不存在的儿子补齐,所以考虑AC自动机。

然后因为AC自动机是在Trie图上建的,距离不能直接求,所以要预处理。

时间复杂度\(O(n)\)

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#include<cassert>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read()
{
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return data*w;
}
template<class T> il T read(T&x)
{
    return x=read<T>();
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1e5+7;

vector<int>a[MAXN];
int d[MAXN];

const int CHARSET=26;
struct Trie
{
    int sz;
    int to[MAXN][CHARSET];
    int nx[MAXN];
    int fa[MAXN];
    int v[MAXN];
    
    il void ins(rg char*s)
    {
        rg int p=0;
        for(;*s;++s)
        {
            rg int c=*s-'a';
            if(to[p][c]==0)
            {
                to[p][c]=++sz;
                fa[sz]=p;
            }
            p=to[p][c];
        }
        v[p]=1;
    }
    
    il void build()
    {
        rg queue<int>Q;
        Q.push(0);
        while(!Q.empty())
        {
            rg int x=Q.front();
            Q.pop();
            v[x]|=v[nx[x]];
            for(rg int i=0;i<CHARSET;++i)
            {
                if(to[x][i])
                {
                    nx[to[x][i]]=x?to[nx[x]][i]:0;
                    Q.push(to[x][i]);
                }
                else
                {
                    to[x][i]=x?to[nx[x]][i]:0;
                }
            }
        }
        for(rg int i=0;i<=sz;++i)
            for(rg int j=0;j<CHARSET;++j)
            {
                a[to[i][j]].push_back(i);
            }
        memset(d,0x3f,sizeof d);
        for(rg int i=0;i<=sz;++i)
            if(v[i])
            {
                Q.push(i);
                d[i]=0;
            }
        while(!Q.empty())
        {
            rg int x=Q.front();
            Q.pop();
            for(rg int i=0;i<a[x].size();++i)
            {
                rg int y=a[x][i];
                if(d[y]>d[x]+1)
                {
                    d[y]=d[x]+1;
                    Q.push(y);
                }
            }
        }
    }
}T;

char s[MAXN],t[MAXN];

int f[MAXN],len;

int main()
{
  freopen("xining.in","r",stdin);
  freopen("xining.out","w",stdout);
    scanf("%s",s);
    T.ins(s);
    T.build();
    scanf("%s",t);
    printf("%d\n",d[f[len]]);
    for(rg int i=0;t[i];++i)
    {
        if(t[i]=='-')
        {
            if(len>0)
                --len;
        }
        else
        {
            rg int x=T.to[f[len]][t[i]-'a']; // edit 1
            f[++len]=x;
        }
//      cerr<<"f="<<f[len]<<endl;
        printf("%d\n",d[f[len]]);
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/autoint/p/9835871.html