https://cn.vjudge.net/contest/239768
A题就很迷,写了剪枝的搜索WA到死,准备拍一下写了个暴力把暴力交了A了。心态炸裂。
C题 给两个集合 从一个集合中挑选至多两个数(可重复选),问能组成多少个另外一个集合中的数。听说是FFT。
H题,二维字符串匹配,学着写白书上的AC自动机,结果因为模板矩阵太大了,T了。然而正解不是优化而是直接写hash,二维hash学习笔记如下。
拓展维数之后应该一维一个base,差点想当然地用的同一个base。这样的话三维hash,想倒是好像就是不太好写。(可能是我不太熟练)然后模板矩阵先压一维(横向压扁),压成一个数组,再次hash成一个数。文本矩阵需要维护一个hash数组,脑补一下,比如说就是一个横行跟模板矩阵大小一样的部分的hash值,这样才能保证向右移动的时候能够O(1)更新一个横行O(n)做完这一列的匹配。 题目在这里:http://codeforces.com/gym/100783/attachments J题
代码这里
//QWsin
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i,x,y) for(int i=x;i<=y;++i)
using namespace std;
typedef unsigned long long ull;
ull baseh=827,bases=1127;
const int maxn=2000+10;
char P[maxn][maxn],M[maxn][maxn];
ull hv[maxn];
int main()
{
int n,m,x,y;cin>>n>>m>>x>>y;
rep(i,1,n) scanf("%s",P[i]+1);
rep(i,1,x) scanf("%s",M[i]+1);
ull STD=0;
rep(i,1,n)
{
ull tmp=0;
rep(j,1,m) tmp=tmp*baseh+P[i][j];
STD=STD*bases+tmp;
}
rep(i,1,x)
{
hv[i]=0;
rep(j,1,m) hv[i]=hv[i]*baseh+M[i][j];
}
ull bases_n=1,baseh_m=1;
rep(i,1,n-1) bases_n=bases_n*bases;
rep(i,1,m-1) baseh_m=baseh_m*baseh;
int ans=0;
rep(j,1,y-m+1)
{
ull cur=0;
rep(i,1,n-1) cur=cur*bases+hv[i];
rep(i,n,x)
{
cur=(cur-hv[i-n]*bases_n)*bases+hv[i];
if(cur==STD)
++ans;
}
rep(i,1,x)
hv[i]=(hv[i]-M[i][j]*baseh_m)*baseh+M[i][j+m];
}
cout<<ans<<endl;
return 0;
}