[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;
}
与你的日常,便是奇迹

浙公网安备 33010602011771号