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; }
时间: 2024-10-17 14:04:17