思路:先把字符串填充好(后面填充的把前面覆盖掉),然后用KMP查找有多少个子串,如果比填充的少,说明有些覆盖矛盾,输出0;否则,设不确定的点的个数为k,答案为(26^k)%(1e9+7)。
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset((a),(b),sizeof(a)) const int N=1e6+5; const int MOD=1e9+7; int f[N]={-1}; bool vis[N]={false}; bool vis1[N]={false}; int main() { ios::sync_with_stdio(false); cin.tie(0); int n,t,a; string s; cin>>n>>t; cin>>s; int tt=t; while(t--) { cin>>a; vis[a-1]=true;//假装填上了,其实也就是标记一下第一个点 } int m=s.size(); for(int i=1;i<m;i++) { int j=f[i-1]; while(s[j+1]!=s[i]&&j>=0)j=f[j]; if(s[j+1]==s[i])f[i]=j+1; else f[i]=-1; } int i=0,j=0,cnt=0; t=-1; while(i<n) { if(vis[i])t=i;//把标记那个点更新一下 if(t!=-1) { if(i-t<m) { vis1[i]=true;//把填过的点标记下 if(s[i-t]==s[j])//本质是s串自己和自己比较啊 { i++; j++; if(j==m) { cnt++; j=f[j-1]+1; } } else { if(j==0)i++; else j=f[j-1]+1; } } else i++; } else i++; } if(cnt<tt) { cout<<0<<endl; return 0; } ll ans=1; for(int i=0;i<n;i++)if(!vis1[i])ans=(ans*26)%MOD; cout<<ans<<endl; return 0; }