Codeforces 452E Three strings 字符串 SAM

原文链接https://www.cnblogs.com/zhouzhendong/p/CF542E.html

题目传送门 - CF452E

题意

  给定三个字符串 $s1,s2,s3$ ,对于所有 $L\in{1,2,\cdots,min(|s1|,|s2|,|s3|)}$ ,输出 $f(L)$ 。

  其中 $f(L)$ 表示满足 $s_k[i_k,\cdots,i_k+L-1]$ 全部相同的 $i_1,i_2,i_3$ 的个数。

  答案对 $10^9+7$ 取模。

  $|s1|+|s2|+|s3|\leq 3\times 10^5$

题解

  第二次写广义后缀自动机,居然又只写了 20 分钟??然而没有看到取模,以及一个取模上面的傻逼错误续了我 15 分钟。

  把三个串全部扔进广义后缀自动机里面。

  对于每一个状态,分别算出属于这三个串的 right 集合大小。

  然后对于每一个节点,方案总数就是 $\prod_{k=0}^{2}right_{i,k}$ ,影响的长度范围是 $(\rm{Max(father),Max(i)}]$ ,相当于区间加,直接差分一下就可以了。

  最后回答的时候前缀和一下就好了。注意取模。

代码

#include <bits/stdc++.h>
#define right __fjw82
using namespace std;
const int N=300005,S=N*2,mod=1e9+7;
char s[N];
int n=1e9,in[S],q[S],ans[N],right[S][3],head,tail;
int root,size;
struct SAM{
	int Next[26],fa,Max;
}t[N<<1];
void init(){
	memset(t,0,sizeof t);
	root=size=1;
	t[0].Max=-1;
	for (int i=0;i<26;i++)
		t[0].Next[i]=1;
}
int extend(int p,int c){
	if (t[p].Next[c]&&t[p].Max+1==t[t[p].Next[c]].Max)
		return t[p].Next[c];
	int np=++size,q,nq;
	t[np].Max=t[p].Max+1;
	for (;!t[p].Next[c];p=t[p].fa)
		t[p].Next[c]=np;
	q=t[p].Next[c];
	if (t[p].Max+1==t[q].Max)
		t[np].fa=q;
	else {
		nq=++size;
		t[nq]=t[q],t[nq].Max=t[p].Max+1;
		t[q].fa=t[np].fa=nq;
		for (;t[p].Next[c]==q;p=t[p].fa)
			t[p].Next[c]=nq;
	}
	return np;
}
int main(){
	init();
	for (int i=0,now;i<3;i++){
		scanf("%s",s+1);
		n=min(n,now=strlen(s+1));
		for (int j=1,p=root;j<=now;j++)
			right[p=extend(p,s[j]-‘a‘)][i]++;
	}
	for (int i=2;i<=size;i++)
		in[t[i].fa]++;
	head=tail=0;
	for (int i=2;i<=size;i++)
		if (in[i]==0)
			q[++tail]=i;
	while (head<tail){
		int x=q[++head];
		for (int i=0;i<3;i++)
			right[t[x].fa][i]+=right[x][i];
		in[t[x].fa]--;
		if (t[x].fa>1&&!in[t[x].fa])
			q[++tail]=t[x].fa;
	}
	memset(ans,0,sizeof ans);
	for (int i=2;i<=size;i++){
		int add=1LL*right[i][0]*right[i][1]*right[i][2]%mod;
		(ans[t[t[i].fa].Max+1]+=add)%=mod;
		(ans[t[i].Max+1]+=mod-add)%=mod;
	}
	for (int i=1;i<=n;i++){
		ans[i]=(ans[i]+ans[i-1])%mod;
		printf("%d ",ans[i]);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhouzhendong/p/CF542E.html

时间: 2024-08-30 09:42:07

Codeforces 452E Three strings 字符串 SAM的相关文章

Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)

原文链接https://www.cnblogs.com/zhouzhendong/p/9256033.html 题目传送门 - CF873F 题意 给定长度为 $n$ 的字符串 $s$,以及给定这个字符串每一个位置是否 "禁止结尾" 的信息. 一个字符串 $a$ 的价值为 $|a|\times f(a)$ . 其中 $f(a)$为 $a$ 在 $s$ 中的匹配次数(如果匹配的结尾为禁止结尾点,那么不算匹配成功) 问在所有的字符串 $a$ 中,$\max(|a|\times f(a)$

[2016-04-26][codeforces][665C - Simple Strings]

时间:2016-04-26 10:11:21 星期二 题目编号:[2016-04-26][codeforces][665C - Simple Strings] 题目大意:给定一个字符串,问最少需要更改多少字符,使得相邻的字母都不一样,输出更改后的字符串 分析: 贪心,从左往右扫一遍数组,更改相同的元素即可 遇到的问题: 注意,相同元素必须更改后面那个元素才是最优的答案. 比如 aaa 这种情况只能更改中间那个 #include<iostream> #include<string>

Codeforces Round #313 (Div. 2) D.Equivalent Strings (字符串)

感觉题意不太好懂 = =# 给两个字符串 问是否等价等价的定义(满足其中一个条件):1.两个字符串相等 2.字符串均分成两个子串,子串分别等价 因为超时加了ok函数剪枝,93ms过的. #include <iostream> #include <cstring> #define clr(x,c) memset(x,c,sizeof(x)) using namespace std; const int N = 200005; char s[N], t[N]; int sc[30],

LeetCode OJ:Multiply Strings (字符串乘法)

Given two numbers represented as strings, return multiplication of the numbers as a string. Note: The numbers can be arbitrarily large and are non-negative. 给出两个字符串,返回对应数字想乘后的字符串,由于这个字符串可能很大,所以不能采用一般的乘法,这里用的方法是模拟手工的乘法运算,算法 本身很简单,就是当时写的时候有些很小的细节搞错了,找了

Codeforces 176B (线性DP+字符串)

题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成新串.问经过K次变形后,与目标串相同的变形方案数.mod 1000000007. 解题思路: 奇葩的字符串DP.照着别人的题解写的,解释不出原理是什么. 首先统计出经过1次变形,就能和目标串相同的中间产物串(包含源串)的个数cnt.len表示源串长度,那么len-cnt就表示和目标串不同的个数. 用

[LeetCode] Multiply Strings 字符串相乘

Given two numbers represented as strings, return multiplication of the numbers as a string. Note: The numbers can be arbitrarily large and are non-negative. 这道题让我们求两个字符串数字的相乘,输入的两个数和返回的数都是以字符串格式储存的,这样做的原因可能是这样可以计算超大数相乘,可以不受int或long的数值范围的约束,那么我们该如何来计算

Codeforces 186A. Comparing Strings

Some dwarves that are finishing the StUDY (State University for Dwarven Youngsters) Bachelor courses, have been told "no genome, no degree". That means that all dwarves should write a thesis on genome. Dwarven genome is far from simple. It is re

Multiply Strings(字符串乘法模拟,包含了加法模拟)

Given two numbers represented as strings, return multiplication of the numbers as a string. Note: The numbers can be arbitrarily large and are non-negative. 要求:字符串表示的数字可能无穷大,并且非负. class Solution { private: vector<string> tempStrs; public: string add

SPOJ LCS2 - Longest Common Substring II 字符串 SAM

原文链接http://www.cnblogs.com/zhouzhendong/p/8982484.html 题目传送门 - SPOJ LCS2 题意 求若干$(若干<10)$个字符串的最长公共连续子串长度. 串长$\leq 100000$ 题解 建议在做本题之前,先去做SPOJ LCS,本题是其升级版. 题解链接 - SPOJ LCS - http://www.cnblogs.com/zhouzhendong/p/8982392.html 对于本题,我们只需要保持一下之后每一个串在第一个串的$