您的位置:首页 > 其它

zoj 3817 2014牡丹江网赛 字符串哈希

2014-09-12 01:44 337 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5349

比赛的时候没看这道题,遗憾,不过想到算法不难,但是写代码比较考代码能力,我自己写了两次都不行,还是看了别人代码,写下了这个

学到:

1、hash字符串第一个下表为0的空起来,写起来方便

2、hash匹配的全部情况就是以text串的所有位置为起点做匹配,当text比patern小而且text可以循环时,这么确定

3、dfs的时候,为了加快,可以预估计至少需要匹配多长

int L=min(len,n+1-st);  这样写法 节省了很多时间

4、注意预处理hash  B的次方 以及字符串的hash

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-8;
const int INF = 100000000;
const ull B=1e8+7;
const int MAXN = 100000+5;
vector< pair<int,int> > ans;
char str[MAXN];
ull ha[9][MAXN],tt[MAXN],hb[MAXN];
//int leg[10],lenp;
int n,m;

void calhb()
{
hb[0]=0;
for(int i=1;i<=m;i++)
hb[i]=hb[i-1]*B+str[i];
}

void read()
{
ans.clear();
scanf("%d%d",&n,&m);
for(int i=0;i<8;i++)
{
scanf("%s", str+1);
int len=strlen(str+1);
//leg[i]=len;
ha[i][0]=0;
for(int j=1;j<=len;j++)
ha[i][j]=ha[i][j-1]*B+str[j];
i++;
reverse(str+1,str+1+strlen(str+1));
for(int j=1;j<=len;j++)
ha[i][j]=ha[i][j-1]*B+str[j];
}
scanf("%s",str+1);
calhb();
}

int dfs(int k, int st, int len)
{
/////////////
//printf("## k=%d st=%d len=%d\n",k,st,len);
//////////////
if(len == 0)return 1;
int L=min(len,n+1-st);

if(ha[k][st+L-1]-ha[k][st-1]*tt[L] == hb[m-len+L]-hb[m-len]*tt[L])
{
ans.push_back(make_pair(k,st));
len-=L;
int bac= k%2?k-1:k+1;
if(len == 0)return 1;
for(int i=0;i<8;i++)
if(i!=bac && dfs(i,1,len))
return 1;
ans.pop_back();
}
return 0;
}

int solve()
{
for(int i=0;i<8;i++)
for(int j=1;j<=n;j++)
{
ans.clear();
if(dfs(i,j,m))
return 1;
}
return 0;
}

vector<int>op;

void out()
{
op.clear();
int cnt=0;
for(int i=0;i<ans.size();i++)
{
//printf("## k==%d st=%d\n",ans[i].first,ans[i].second);
if(ans[i].first%2 == 0)//正序
{
for(int j=ans[i].second; j<=n && cnt<m; j++)
{
op.push_back(ans[i].first/2*n+j);
cnt++;
}
}
else
{
for(int j=ans[i].second; j<=n && cnt<m; j++)
{
op.push_back(ans[i].first/2*n+n-j+1);
cnt++;
}
}
}
printf("%d",op[0]);
for(int i=1;i<op.size();i++)
printf(" %d",op[i]);
putchar('\n');
}

int main()
{
//IN("zoj3810.txt");
int ncase;
scanf("%d",&ncase);
tt[0]=1;
for(int i=1;i<MAXN;i++)
tt[i]=tt[i-1]*B;
while(ncase--)
{
read();
if(solve())
out();
else
puts("No solution!");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: