Codeforces 535D - Tavas and Malekas

535D - Tavas and Malekas

题目大意:给你一个模板串,给你一个 s 串的长度,告诉你 s 串中有 m 个模板串并告诉你,他们的其实位置,

问你这样的 s 串总数的多少,答案对1e9+7取模。

 

我感觉我英语是不是不行啊,我以为他的意思是他里面一共只有m个匹配串,想着没有其他的匹配串,感觉

好麻烦好麻烦好麻烦啊!!!!!!

 

思路:最暴力的思路,他给你一个匹配串的位置,你就在s串上更新,如果遇到没有已经被更新而且字符不同时

输出0,然后统计剩下的未知字符的个数x,答案就是 (26^x)%mod。这样可能会超时,我今天学习了一波

KMP(看毛片)算法,这玩意真的有点难理解,以后多理解几遍。 

我们可以在更新s串的时候只更新后面没有更新的,然后用kmp扫一遍,看m个匹配串是否都出现过就好了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;
const ll mod=1e9+7;
char s[N],t[N];
int nx[N];
int len1,len2,n,m,w[N],c=0;
void get_next()
{
    int k=0;
    for(int i=1;i<len2;i++)
    {
        while(k>0 && t[k]!=t[i]) k=nx[k-1];
        if(t[k]==t[i]) k++;
        nx[i]=k;
    }
}
void kmp()
{
    int k=0;
    for(int i=0;i<n;i++)
    {
        while(k>0 && t[k]!=s[i]) k=nx[k-1];
        if(t[k]==s[i]) k++;
        if(k==len2)
        {
            if(binary_search(w,w+m,i-k+1)) c++;
        }
    }
}
int main()
{
    cin>>n>>m;
    scanf("%s",t);
    len2=strlen(t);
    for(int i=0;i<n;i++) s[i]='?';
    s[n]='\0';
    for(int i=0;i<m;i++) scanf("%d",&w[i]),w[i]-=1;
    sort(w,w+m);
    m=unique(w,w+m)-w;
    int last=-1;
    for(int i=0;i<m;i++)
    {
        if(w[i]+len2-1>last)
        {
            int start=w[i],dis=0;
            if(last+1>w[i])
            {
                dis=last+1-w[i];//dis为相对模板串开头的偏移位置。
                start=last+1;
            }
            for(int j=start;j<=w[i]+len2-1;j++) s[j]=t[j-start+dis];
            last=w[i]+len2-1;
        }
    }
    //puts(s);
    get_next();
    kmp();
    if(c<m)
    {
        puts("0");
        return 0;
    }
    ll res=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='?') res+=1;
    }
    ll ans=1;
    for(int i=1;i<=res;i++)
    {
        ans=(ans*(ll)26)%mod;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

 

posted @ 2017-08-16 18:46  NotNight  阅读(451)  评论(0编辑  收藏  举报