2014牡丹江网络预选赛I题(字符串hash+简单DP)zoj3817

Chinese Knot

Time Limit: 2 Seconds       Memory Limit: 65536 KB       Special Judge

Chinese knot is a decorative handicraft that began as a form of Chinese folk artifact in the Tang and Song Dynasty in China. It was later popularized in the Ming.

Alice is learning Chinese knotting. To take the first step, she went to the store and bought a string. To her surprise, she found the string was composed of characters! Anyway, she made a simple Chinese knot. It consists of one knot with 4 loops:

Look at the picture above. There are four loops connected at the center black knot. To make the image clear and neat, the characters on the string are shown as red and yellow points. As a Mid-Autumn Festival gift, Alice give this handcrafted Chinese knot to you. Then she asked you a question:

You are given a target character sequence. Can you get the sequence by walking on the knot? "Walking on the knot" means:

  • You can start at any point you want.
  • You can not start at or move to the black knot in the center.
  • Each step, you can only move to an adjacent point, except for the point you came from immediately.
  • The 8 points closely around the black knot are adjacent to each other. For example, in the picture above, they are the 8 yellow points adjacent to the black knot.
  • Your path should not contain three continuous points which are both one of the 8 points mentioned above.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains two integers N and M (3 <= NM <= 100000). The total length of string that Alice bought from store is 4 * N.

Then followed by 4 lines, each line contains N lower case letters as a loop of the Chinese knot. These characters are indexed from 1 to 4 * N corresponding to the input order.

The next line contains M lower case letters indicating the target character sequence.

Output

For each test case, output the M indexes of characters you visited. If there are multiple solutions, output any one. If there is no solution, output "No solution!" instead.

Sample Input
2
3 3
abc
abc
abc
abc
baa
3 3
abc
abc
abc
abc
bab
Sample Output
2 1 4
No solution!
Hint

In the first case, we start at the second character of the first loop and stop at the first character of the second loop.


题意:RT

思路:字符串hash

            将4个模式串正着反着构造出字符串hash,那么一共就是8个串了

            然后for一遍文本串,判断每个位置 i 是否可以以该位置的字符为开头将第 j 个模式串放进去,能放则qx[ i ][ j ]=true

            之后就是简单的DP了

            DP[i][j]表示由第 j 个模式串为结尾跑到了文本串的第 i 个字符

            转移:如果DP[i][j] 为真,那么在i+1个位置可以选择任意其它7个模式串继续跑,因为与第j个模式串为相反的不能选(不能再倒回去跑)

            因为题目还要求打印方案,所以DP数组可以存 放的模式串的长度,既可以起到判断可行,也可以起到最后打印方案的作用

            最后注意一下开头和结尾,特殊判断一下即可

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          #include 
          #include 
          
            #include 
           
             #include 
            
              using namespace std; #define maxn 100010 #define mod 1000000009 #define mul 31 typedef long long ll; int pw[maxn]; char s[maxn]; int n,m; int mini(int x,int y) { return x 
             
               =m && H[i].query(j,j+len-1)==Ht.query(1,len)) { int L=(i/2)*n; for(int k=j;k 
              
                =1;) { for(int j=0;j<8;j++) { if(j!=(vis^1) && dp[i][j]) { int L=j/2*n; int len=dp[i][j]; if(i==m || (i 
               
                 =1;k--) stk[cnt++]= ( j&1 ? n-k+1+L : k+L ); } else if(len 
                
                  =n-len+1;k--) stk[cnt++]= (j&1 ? n-k+1+L : k+L ); } i-=dp[i][j]; vis=j; break; } } } for(int i=cnt-1;i>0;i--)printf("%d ",stk[i]); printf("%d\n",stk[0]); return 1; } int main() { int t; pw[0]=1; for(int i=1;i<=maxn-10;i++)pw[i]=(ll)pw[i-1]*mul%mod; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=0;i<8;i+=2) { scanf("%s",s); H[i].init(s); reverse(s,s+n); H[i^1].init(s); } scanf("%s",s); Ht.init(s); if(!solve())printf("No solution!\n"); } return 0; } 
                 
                
               
              
             
            
           
         
       
      
      
     
     
    
    
   
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值