卧薪尝胆,厚积薄发。
字符串匹配
Date: Wed Oct 03 07:48:12 CST 2018
In Category:
NoCategory
Description:
给定两个字符串,分别复制
$n,m$
倍,保证最后长度相同,问有几个字符对应相等。
$1\leqslant n,m \leqslant10^9,1\leqslant|S|,|T|\leqslant 10^6$
Solution:
首先假设
$\gcd(|S|,|T|)=1$
,那么发现由于互质的两个数某个数的倍数会遍历另一个数的剩余系,所以
$|S|$
中的每个字符都会和
$|T|$
中的字符匹配一下,所以开个桶记录
$|S|$
的每个字符出现次数再枚举
$|T|$
的每个字符累加答案,如果
$\gcd$
不为
$1$
,那么可以看成是很多长为
$\gcd$
的段,每一段都会互相遍历一次,所以开一个
$n\times26$
的桶记录每个字符
$\%gcd$
的值,用桶记录一下,然后还是用第二个串累加答案就行了。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m;
#define MAXL 1000010
char S[MAXL],T[MAXL];
int Sl,Tl;
long long len;
int gcd(int a,int b){return (b == 0 ? a : gcd(b,a % b));}
int cnt[MAXL][26];
int main()
{
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
scanf("%d%d",&n,&m);
scanf("%s%s",S + 1,T + 1);
Sl = strlen(S + 1);Tl = strlen(T + 1);
len = (long long)Sl * n;
int g = gcd(Sl,Tl);
long long ans = 0;
for(int i = 1;i <= Sl;++i)++cnt[i % g][S[i] - 'a'];
for(int i = 1;i <= Tl;++i)ans += cnt[i % g][T[i] - 'a'];
cout << ans * (len / (long long)((long long)Sl / g * Tl)) << endl;
fclose(stdin);
fclose(stdout);
return 0;
}
In tag:
数学-同余
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡