cf#299 Tavas and Malekas

传送门在这里

题意:给出一个字符串的一个子串,告诉你子串在某些位置和原串匹配,求一共有多少可能的原串

思路:其实就是要判断给出子串的所有前缀和后缀哪些是相等的。

首先kmp的next数组求的是所有前缀子串(a1  a1a2  a1a2a3...)中长度最大的前缀和后缀的长度,

设字符串长度为len,那么next[len]得到的是整个字符串中长度最长的相等的前缀和后缀,并且可知,所有起始位置小于next[len]的后缀都不可能存在相等的前缀了,那么下一步就是求起始位置在[next[len]+1,len]中的所有相等后缀。

假设长度第二的相等后缀位置为pos,显然有a[1]a[2]..a[k]=a[pos]a[pos+1]..a[pos+k-1],这里pos+k-1==len并且k<next[len],我们要求的k其实就是a[1]a[2]...a[next[len]]这个前缀子串中最长的相等前缀的和后缀,即k=nextnext[len]].于是我们可以找出所有相等的前缀和后缀的位置。

代码:

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<map>
#include<set>
using namespace std;
#define Mod 1000000007

char s[1000005];
int a[1000005];
int len;
int next[1000005];
int v[1000005];

void getnext(char* s){
	next[0]=next[1]=0;
	for(int i=1;i<len;i++){
		int j=next[i];
		while(j&&s[i]!=s[j]) j=next[j];
		if(s[i]==s[j]) next[i+1]=j+1;
		else next[i+1]=0;
	}
}

int main(){
	int i,j;
	int n,m;
	scanf("%d%d",&n,&m);
	scanf("%s",s);
	for(i=1;i<=m;i++){
		scanf("%d",&a[i]);
	}
	len=strlen(s);
	if(m==0){
		long long ans=1;
		for(i=1;i<=n;i++){
			ans=ans*26%Mod;
		}
		cout<<ans<<endl;
		return 0;
	}
	getnext(s);
	for(i=len;next[i];i=next[i]){
		v[len-next[i]]=1;
	}
	long long ans=1;
	for(i=1;i<a[1];i++){
		ans=ans*26%Mod;
	}
	for(i=2;i<=m;i++){
		if(a[i-1]+len<=a[i]){
			for(j=a[i-1]+len;j<a[i];j++){
				ans=ans*26%Mod;
			}
		}
		else{
			int pos=a[i]-a[i-1];
			if(!v[pos]){
				ans=0;
				break;
			}
		}
	}
	for(i=a[m]+len;i<=n;i++){
		ans=ans*26%Mod;
	}
	cout<<ans<<endl;
	return 0;
}
时间: 2024-08-02 15:12:33

cf#299 Tavas and Malekas的相关文章

Codeforces 535D - Tavas and Malekas

535D - Tavas and Malekas 题目大意:给你一个模板串,给你一个 s 串的长度,告诉你 s 串中有 m 个模板串并告诉你,他们的其实位置, 问你这样的 s 串总数的多少,答案对1e9+7取模. 我感觉我英语是不是不行啊,我以为他的意思是他里面一共只有m个匹配串,想着没有其他的匹配串,感觉 好麻烦好麻烦好麻烦啊!!!!!! 思路:最暴力的思路,他给你一个匹配串的位置,你就在s串上更新,如果遇到没有已经被更新而且字符不同时 输出0,然后统计剩下的未知字符的个数x,答案就是 (26

【Codeforces 536B】Tavas and Malekas

536B Tavas and Malekas 题意:给一个字符串,现在要把这个字符串在一个大空字符串中放多次,每一次的开头在\(p_i\)位置,然后现在问这个大字符串有多少种情况. 思路:首先如果两个字符串放置的位置有重叠,重叠部分必须相等. 那么就是一个前缀要等于一个后缀. 所以果断z function.这样的话写起来比kmp快... 然后就可以对于每两个连续出现判断这些重复部分的交叉状况,同时算上所有的非自由的字符,最后求出\(2^{自由字符数量}\)即可. 原文地址:https://www

Codeforces Round #299 (Div. 2)D. Tavas and Malekas

KMP,先预处理按每个节点标记,扫一遍更新每个匹配位置,最后kmp判断是否有重合而且不相同的地方 注意处理细节,很容易runtime error #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cassert> #inclu

codeforces535D:Tavas and Malekas(KMP)

Tavas is a strange creature. Usually "zzz" comes out of people's mouth while sleeping, but string s of length n comes out from Tavas' mouth instead. Today Tavas fell asleep in Malekas' place. While he was sleeping, Malekas did a little process o

CF 535c Tavas and Karafs

Tavas and Karafs Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 535C Description Karafs is some kind of vegetable in shape of an 1 × h rectangle. Tavaspolis people love Karafs and they

codeforces 535D. Tavas and Malekas KMP

题目链接 又复习了一遍kmp....之前都忘光了 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_pair(x, y) 6 #define lson l, m, rt<<1 7 #define mem(a) memset(a, 0, sizeof(a)) 8 #define rson

Codeforces 536B Tavas and Malekas 求自身首尾的重叠位置 KMP

题目链接:点击打开链接 题意: 用小写字母构造n长的串S,m个要求 字符串P 下面m个位置.a1, a2···am(输入有序) 要使得字符串S的以ai 开头且后面是一个P串. 问构造的方法数 思路: 实际上,对于ai, ai+1 ,两个位置,如果这两个位置会相互影响(即 ai+1 - ai < len) 复制一个和P一样的串P' 把P放在ai位置,把P'放在ai+1位置,那么只需要判断一下 P的后半段是否和P'的前半段匹配即可. 也就是P'的哪些位置是和P的尾部相同的. KMP求出这些位置放到s

【codeforces #299(div 1)】ABC题解

A. Tavas and Karafs time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard output Karafs is some kind of vegetable in shape of an 1?×?h rectangle. Tavaspolis people love Karafs and they use Karafs in almost

屯题大法好

CF 535C Tavas and Karafs 题目大意:给你一个无限长的等差数列,每次给一个起点L,可以吃T轮,每可以把M个数吃一口(-1),问最大的R使得区间[L,R]被吃完 思路:显然给定一个区间[L,R]后很容易贪心出能不能被吃完,并且发现该性质有单调性也就是如果[L,R]可以吃完,那[L,R-1]也可以,且存在最大的R使得[L,R+1]不满足条件,于是二分一下就可以了 1 #include<iostream> 2 #include<cstdio> 3 #define l