给你两个字符串a和b,a的长度为n,匹配的位置有m个。若b在a中的一定匹配的位置为\(x_1,x_2,...,x_m\) , 求不同的字符串a的数量。
相邻两个子串b在a中匹配位置有两种情况:
注意:
\(m==0\) 时,\(ans=26^n\)
若当前字符串右边界已经超过a的长度\(n\),则直接判0
注意匹配位置判断完毕后,还要用当前右边界到\(n\)的距离更新答案
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 1000010,mod=1e9+7;
long long ans;
int n,m;
string s;
int z[N];
int p[N];
void z_function(string s) 
{   
    int n = s.size();
    for (int i = 1, l = 0, r = 0; i < n; ++i) 
    {
        if (i <= r) z[i] = min(r - i + 1, z[i - l]);
        while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i];
        if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    cin>>s;
    
    z_function(s);
    
    p[0]=1;
    for(int i=1;i<=1000000;i++) p[i]=1ll*p[i-1]*26%mod;
    
    if(m==0)
    {
        printf("%d\n",p[n]);
        return 0;
    }
    
    int r;//表示当前的右边界 
    int len=s.size();
    for(int i=1;i<=m;i++)
    {
        int x;
        scanf("%d",&x);
        
        if(i==1)
        {
            ans=p[x-1];
            r=x+len-1;
            continue;
        }
        
        if(x>r) ans=ans*p[x-r-1]%mod;
        else
        {
            if(z[x-r+len-1]<r-x+1)
            {
                puts("0");
                return 0;
            }
        }
        
        r=x+len-1;
        
        if(r>n)
        {
            puts("0");
            return 0;
        }
    }
    
    if(r<n) ans=ans*p[n-r]%mod;
    cout<<ans<<endl;
    
    return 0; 
}Codeforces535D Tavas and Malekas
原文:https://www.cnblogs.com/zjling/p/12443893.html