A
B

[USACO05DEC] Cow Patterns G 代码

BZOJ1461字符串的匹配

[USACO05DEC] Cow Patterns G

//[USACO05DEC] Cow Patterns G
//P6080
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define Blue_Archive return 0
#define rint register int
using namespace std;
const ull P = 998244353ull;
const int N = 100010;
const int M = 30;

int n;
int k;
int s;
int a[N];
int b[N];
int ans[N];
int top;

ull hs[M];
ull pw[N];
ull toth;
ull sum[M];
int ls[M];	
int cnt;

inline void PPPPP()//预处理
{
	pw[0] = 1; 
	for(int i = 1;i <= n;i ++) pw[i] = P * pw[i - 1];
}



inline void check(int x)
{
	int num = 0;
	ull now = 0;
	for(int i = 1;i <= s;i ++) 
	{
		if(sum[i])//在1~s中出现过的数 
		{
			now += sum[i] * hs[++ num];//求哈希
		}
	}
	if(now == toth * pw[x - 1])//如果与b字符串哈希值相等
	{
		ans[++ top] = x;//记录结果
	} 
}

signed main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	cin >> k;
	cin >> s;
	PPPPP();
	srand(time(0));
	for(int i = 1;i <= s;i ++) hs[i] = P * rand() * rand();//高级哈希,P乘两遍随机数
	for(int i = 1;i <= n;i ++) cin >> a[i];//读入a字符串
	for(int i = 1;i <= k;i ++)//读入b字符串
	{
		cin >> b[i];
		ls[b[i]] ++;//记录1~s中出现的数字
	}
	for(int i = 1;i <= s;i ++) 
	{
		if(ls[i])//将记录过的数字标序
		{
			ls[i] = ++ cnt;//从1开始
		} 
	}
	for(int i = 1;i <= k;i ++) toth += pw[i] * hs[ls[b[i]]];//求b串的哈希,记在toth变量中

	for(int i = 1;i <= k;i ++) sum[a[i]] += pw[i];

	check(1);
	
	for(int l = 2,r = k + 1;r <= n;l ++,r ++)//将“窗口”向后移动
	{
		sum[a[l-1]] -= pw[l-1];//减去l-1の哈希
		sum[a[r]] += pw[r];//加上rの哈希
		check(l);//前去比较
	}
	
	cout << top << "\n";//输出结果数

	for(int i = 1;i <= top;i ++) cout << ans[i] << "\n";//输出结果

	Blue_Archive;
}
posted @ 2025-07-31 06:45  MyShiroko  阅读(7)  评论(0)    收藏  举报